Railway Operation Simulator  v2.6.1
A railway simulator for Windows
InterfaceUnit.cpp
Go to the documentation of this file.
1 // InterfaceUnit.cpp
2 /*
3  BEWARE OF COMMENTS in .cpp files: they were accurate when written but have
4  sometimes been overtaken by changes and not updated
5  Comments in .h files are believed to be accurate and up to date
6 
7  This is a source code file for "railway.exe", a railway operation
8  simulator, written originally in Borland C++ Builder 4 Professional with
9  later updates in Embarcadero C++Builder 10.2.
10  Copyright (C) 2010 Albert Ball [original development]
11 
12  This program is free software: you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation, either version 3 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program. If not, see <http://www.gnu.org/licenses/>.
24 */
25 // ---------------------------------------------------------------------------
26 
27 #include <Classes.hpp>
28 #include <Controls.hpp>
29 #include <StdCtrls.hpp>
30 #include <Forms.hpp>
31 #include <Buttons.hpp>
32 #include <ExtCtrls.hpp>
33 #include <Menus.hpp>
34 #include <Dialogs.hpp>
35 #include <Graphics.hpp>
36 #include <ComCtrls.hpp>
37 #include <fstream>
38 #include <vector>
39 #include <vcl.h>
40 #include <stdio.h>
41 #include <algorithm> //for sort
42 
43 #pragma hdrstop
44 // The above batch of include files above #pragma hdrstop appear in all .cpp files.
45 // They aren't all needed in each case but being together and identical they speed
46 // up compilation considerably (without ~14 min, with ~1 min!). They are used in
47 // conjunction with 'use pre-compiled headers' in the project compiler options.
48 
49 #include "InterfaceUnit.h"
50 #include "GraphicUnit.h"
51 #include "DisplayUnit.h"
52 #include "TextUnit.h"
53 #include "TrainUnit.h"
54 #include "Utilities.h"
55 #include "TrackUnit.h"
56 #include "AboutUnit.h"
57 #include <fstream>
58 #include <dirent.h>
59 #include <Filectrl.hpp> //to check whether directories exist
60 
61 // ---------------------------------------------------------------------------
62 #include <Vcl.HTMLHelpViewer.hpp> //added at v2.0.0 for access to the .chm help file
63 #pragma package(smart_init)
64 #pragma link "Vcl.HTMLHelpViewer" //added at v2.0.0 for access to the .chm help file
65 #pragma resource "*.dfm"
66 
68 
69 // Folder Names
70 const UnicodeString TInterface::RAILWAY_DIR_NAME = "Railways";
71 const UnicodeString TInterface::TIMETABLE_DIR_NAME = "Program timetables";
72 const UnicodeString TInterface::PERFLOG_DIR_NAME = "Performance logs";
73 const UnicodeString TInterface::SESSION_DIR_NAME = "Sessions";
74 const UnicodeString TInterface::IMAGE_DIR_NAME = "Images";
75 const UnicodeString TInterface::FORMATTEDTT_DIR_NAME = "Formatted timetables";
76 const UnicodeString TInterface::USERGRAPHICS_DIR_NAME = "Graphics";
77 
78 // ---------------------------------------------------------------------------
79 
80 __fastcall TInterface::TInterface(TComponent* Owner): TForm(Owner)
81 { // constructor
82  try
83  {
84  Screen->Cursor = TCursor(-11); // Hourglass
85  DirOpenError = false;
86  AllSetUpFlag = false; // flag to prevent MasterClock from being enabled when application activates if there has been an error during
87  // initial setup
88  // MasterClock->Enabled = false;//keep this stopped until all set up (no effect here as form not yet created, made false in object insp)
89  // Visible = false; //keep the Interface form invisible until all set up (no effect here as form not yet created, made false in object insp)
91  // use GNU Major/Minor/Patch version numbering system, change for each published modification, Dev x = interim internal
92  // development stages (don't show on published versions)
93 
94  // check for presence of directories, creation failure probably indicates that the
95  // working folder is read-only
96  CurDir = GetCurrentDir();
97  if(!DirectoryExists(RAILWAY_DIR_NAME))
98  {
99  if(!CreateDir(RAILWAY_DIR_NAME))
100  {
101  DirOpenError = true;
102  }
103  }
104  if(!DirectoryExists(TIMETABLE_DIR_NAME))
105  {
106  if(!CreateDir(TIMETABLE_DIR_NAME))
107  {
108  DirOpenError = true;
109  }
110  }
111  if(!DirectoryExists(PERFLOG_DIR_NAME))
112  {
113  if(!CreateDir(PERFLOG_DIR_NAME))
114  {
115  DirOpenError = true;
116  }
117  }
118  if(!DirectoryExists(SESSION_DIR_NAME))
119  {
120  if(!CreateDir(SESSION_DIR_NAME))
121  {
122  DirOpenError = true;
123  }
124  }
125  if(!DirectoryExists(IMAGE_DIR_NAME))
126  {
127  if(!CreateDir(IMAGE_DIR_NAME))
128  {
129  DirOpenError = true;
130  }
131  }
132  if(!DirectoryExists(FORMATTEDTT_DIR_NAME))
133  {
134  if(!CreateDir(FORMATTEDTT_DIR_NAME))
135  {
136  DirOpenError = true;
137  }
138  }
139  if(!DirectoryExists(USERGRAPHICS_DIR_NAME))
140  {
141  if(!CreateDir(USERGRAPHICS_DIR_NAME))
142  {
143  DirOpenError = true;
144  }
145  }
146  if(DirOpenError)
147  {
148  ShowMessage("Failed to create one or more of folders: " + RAILWAY_DIR_NAME + ", " + TIMETABLE_DIR_NAME + ", " + PERFLOG_DIR_NAME + ", " +
150  "program operation may be restricted");
151  }
152 
153  Application->HelpFile = AnsiString(CurDir + "\\Help.chm"); // added at v2.0.0 for .chm help file
154 
155  MainMenu1->AutoHotkeys = maManual; // Embarcadero mod: to suppress '&' inclusion for underlined characters in menu items
156  PopupMenu->AutoHotkeys = maManual; // as above
157 
158  Utilities = new TUtilities;
159  RailGraphics = new TRailGraphics();
160 
161  int DispW = (Screen->Width - 64) / 16; // will truncate down to a multiple of 16 OK here as screen dimensions are accurate
162  int DispH = (Screen->Height - 192) / 16; // Interface dimensions are 16 too wide & 14 short in height
163  MainScreen->Width = DispW * 16;
164  MainScreen->Height = DispH * 16;
165 
168  Utilities->ScreenElementWidth = DispW;
170  HiddenScreen = new TImage(Interface);
171  HiddenScreen->Width = MainScreen->Width;
172  HiddenScreen->Height = MainScreen->Height;
176  Track = new TTrack;
177  AllRoutes = new TAllRoutes;
182  SelectBitmap = new Graphics::TBitmap;
183  SelectBitmap->PixelFormat = pf8bit;
184  SelectBitmap->Transparent = true;
189  LengthWarningSentFlag = false;
190  PasteWarningSentFlag = false; //added at v2.6.0
191  FillSelectionMessageSentFlag = false; //added at v2.6.0
192  LCManualLowerBarriersMessageSent = false; //added at v2.6.0
193 
194  TrackInfoOnOffMenuItem->Caption = "Show"; // added here at v1.2.0 because dropped from ResetAll()
195  TrainStatusInfoOnOffMenuItem->Caption = "Hide Status"; // changed at v2.0.0 so normally visible
196  TrainTTInfoOnOffMenuItem->Caption = "Hide Timetable"; // as above
197  ResetAll(0);
198 
199  TempTTFileName = "";
200 
205 
206  RouteFlashDuration = 0.0;
207  PointsFlashDuration = 0.0;
208 
209  FloatingLabel->Color = clB4G5R5;
210  TrackElementPanel->Color = clB5G5R4;
211  InfoPanel->Color = clB4G5R5;
212 
213  LoadUserGraphicDialog->InitialDir = CurDir + "\\" + USERGRAPHICS_DIR_NAME; //not changeable
214 
215  Utilities->RHSignalFlag = false; // new at v2.3.0 for RH signals, always left hand on startup
216  SigsOnLeftImage1->Picture->Bitmap->LoadFromResourceName(0, "SigsOnLeft");
217  SigsOnLeftImage2->Picture->Bitmap->LoadFromResourceName(0, "SigsOnLeft");
218  SigsOnLeftImage1->Transparent = true;
219  SigsOnLeftImage2->Transparent = true;
220  SigsOnLeftImage1->Picture->Bitmap->TransparentColor = clB5G5R5;
221  SigsOnLeftImage2->Picture->Bitmap->TransparentColor = clB5G5R5;
222  SigsOnRightImage1->Picture->Bitmap->LoadFromResourceName(0, "SigsOnRight");
223  SigsOnRightImage2->Picture->Bitmap->LoadFromResourceName(0, "SigsOnRight");
224  SigsOnRightImage1->Transparent = true;
225  SigsOnRightImage2->Transparent = true;
226  SigsOnRightImage1->Picture->Bitmap->TransparentColor = clB5G5R5;
227  SigsOnRightImage2->Picture->Bitmap->TransparentColor = clB5G5R5;
228 
229  SaveRailwayDialog->InitialDir = CurDir + "\\" + RAILWAY_DIR_NAME; //default locations if not updated from Config.txt
230  LoadRailwayDialog->InitialDir = CurDir + "\\" + RAILWAY_DIR_NAME;
231  TimetableDialog->InitialDir = CurDir + "\\" + TIMETABLE_DIR_NAME;
232  SaveTTDialog->InitialDir = CurDir + "\\" + TIMETABLE_DIR_NAME;
233  LoadSessionDialog->InitialDir = CurDir + "\\" + SESSION_DIR_NAME;
234 
235  std::ifstream ConfigFile((CurDir + "\\Config.txt").c_str()); //added at v2.6.0 to set save & load directories for railways, timetables & session & to
236  if(ConfigFile.fail()) //no Config file //replace Signal.hnd, Background.col and GNU
237  {
238  ConverttoRightHandSignalsMenuItem->Caption = "Convert to Right Hand Signals";
239  SigImagePanel->Caption = "Signals will be on the left hand side of the track";
240  SigsOnLeftImage1->Visible = true;
241  SigsOnLeftImage2->Visible = true;
242  SigsOnRightImage1->Visible = false;
243  SigsOnRightImage2->Visible = false;
244  ShowMessage(
245  "This program is free software released under the terms of the GNU General Public License Version 3, as published by the Free Software Foundation. "
246  "It may be used or redistributed in accordance with that license and is released in the hope that it will be useful, but WITHOUT ANY WARRANTY; "
247  "without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details - "
248  "you should have received a copy along with this program but if not see <http://www.gnu.org/licenses/>.");
249  }
250  else
251  {
252  AnsiString ConfigStr = "";
253  do
254  {
255  Utilities->CheckAndReadFileString(ConfigFile, ConfigStr);
256  if(ConfigFile.eof())
257  {
258  break;
259  }
260  AnsiString ConfigValue = ConfigStr.SubString(9, ConfigStr.Length() - 8);
261  if(ConfigStr.SubString(1, 8) == "Signals=")
262  {
263  if(ConfigValue == "right")
264  {
265  RailGraphics->ConvertSignalsToOppositeHand(1); // always left hand initially when start program, toggles Utilities->RHSignalFlag
266  ConverttoRightHandSignalsMenuItem->Caption = "Convert to Left Hand Signals";
268  {
270  }
271  else
272  {
274  }
275  SigImagePanel->Caption = "Signals will be on the right hand side of the track";
276  SigsOnLeftImage1->Visible = false;
277  SigsOnLeftImage2->Visible = false;
278  SigsOnRightImage1->Visible = true;
279  SigsOnRightImage2->Visible = true;
280  }
281  else
282  {
283  ConverttoRightHandSignalsMenuItem->Caption = "Convert to Right Hand Signals";
284  SigImagePanel->Caption = "Signals will be on the left hand side of the track";
285  SigsOnLeftImage1->Visible = true;
286  SigsOnLeftImage2->Visible = true;
287  SigsOnRightImage1->Visible = false;
288  SigsOnRightImage2->Visible = false;
289  }
290  }
291  if(ConfigStr.SubString(1, 8) == "BgndCol=")
292  {
293  // pick up transparent colour from file if there is one & set it to the stored value if it's valid else set to black
294  Utilities->clTransparent = clB0G0R0; // default black background;
295  if(ConfigValue == "white")
296  {
297  Utilities->clTransparent = TColor(0xFFFFFF);
298  }
299  else if(ConfigValue == "blue")
300  {
301  Utilities->clTransparent = TColor(0x330000);
302  }
303  }
304  if(ConfigStr.SubString(1, 8) == "RLYLocn=")
305  {
306  if(DirectoryExists(ConfigValue)) //e;se stays as original directory
307  {
308  SaveRailwayDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
309  LoadRailwayDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
310  }
311  }
312  else if(ConfigStr.SubString(1, 8) == "TTBLocn=")
313  {
314  if(DirectoryExists(ConfigValue)) //e;se stays as original directory
315  {
316  TimetableDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
317  SaveTTDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
318  }
319  }
320  else if(ConfigStr.SubString(1, 8) == "SSNLocn=")
321  {
322  if(DirectoryExists(ConfigValue)) //e;se stays as original directory
323  {
324  LoadSessionDialog->InitialDir = ConfigStr.SubString(9, ConfigStr.Length() - 8);
325  }
326  }
327  }
328  while(!ConfigFile.eof());
329  ConfigFile.close();
330  }
331 
332  SpeedButton1->Glyph->LoadFromResourceName(0, "gl1");
333  SpeedButton2->Glyph->LoadFromResourceName(0, "gl2");
334  SpeedButton3->Glyph->LoadFromResourceName(0, "gl3");
335  SpeedButton4->Glyph->LoadFromResourceName(0, "gl4");
336  SpeedButton5->Glyph->LoadFromResourceName(0, "gl5");
337  SpeedButton6->Glyph->LoadFromResourceName(0, "gl6");
338  SpeedButton7->Glyph->LoadFromResourceName(0, "gl7");
339  SpeedButton8->Glyph->LoadFromResourceName(0, "gl8");
340  SpeedButton9->Glyph->LoadFromResourceName(0, "gl9");
341  SpeedButton10->Glyph->LoadFromResourceName(0, "gl10");
342  SpeedButton11->Glyph->LoadFromResourceName(0, "gl11");
343  SpeedButton12->Glyph->LoadFromResourceName(0, "gl12");
344  SpeedButton13->Glyph->LoadFromResourceName(0, "gl13");
345  SpeedButton14->Glyph->LoadFromResourceName(0, "gl14");
346  SpeedButton15->Glyph->LoadFromResourceName(0, "gl15");
347  SpeedButton16->Glyph->LoadFromResourceName(0, "gl16");
348  SpeedButton18->Glyph->LoadFromResourceName(0, "gl18");
349  SpeedButton19->Glyph->LoadFromResourceName(0, "gl19");
350  SpeedButton20->Glyph->LoadFromResourceName(0, "gl20");
351  SpeedButton21->Glyph->LoadFromResourceName(0, "gl21");
352  SpeedButton22->Glyph->LoadFromResourceName(0, "gl22");
353  SpeedButton23->Glyph->LoadFromResourceName(0, "gl23");
354  SpeedButton24->Glyph->LoadFromResourceName(0, "gl24");
355  SpeedButton25->Glyph->LoadFromResourceName(0, "gl25");
356  SpeedButton26->Glyph->LoadFromResourceName(0, "gl26");
357  SpeedButton27->Glyph->LoadFromResourceName(0, "gl27");
358  SpeedButton28->Glyph->LoadFromResourceName(0, "gl28");
359  SpeedButton29->Glyph->LoadFromResourceName(0, "gl29");
360  SpeedButton30->Glyph->LoadFromResourceName(0, "gl30");
361  SpeedButton31->Glyph->LoadFromResourceName(0, "gl31");
362  SpeedButton32->Glyph->LoadFromResourceName(0, "gl32");
363  SpeedButton33->Glyph->LoadFromResourceName(0, "gl33");
364  SpeedButton34->Glyph->LoadFromResourceName(0, "gl34");
365  SpeedButton35->Glyph->LoadFromResourceName(0, "gl35");
366  SpeedButton36->Glyph->LoadFromResourceName(0, "gl36");
367  SpeedButton37->Glyph->LoadFromResourceName(0, "gl37");
368  SpeedButton38->Glyph->LoadFromResourceName(0, "gl38");
369  SpeedButton39->Glyph->LoadFromResourceName(0, "gl39");
370  SpeedButton40->Glyph->LoadFromResourceName(0, "gl40");
371  SpeedButton41->Glyph->LoadFromResourceName(0, "gl41");
372  SpeedButton42->Glyph->LoadFromResourceName(0, "gl42");
373  SpeedButton43->Glyph->LoadFromResourceName(0, "gl43");
374  SpeedButton44->Glyph->LoadFromResourceName(0, "gl44");
375  SpeedButton45->Glyph->LoadFromResourceName(0, "gl45");
376  SpeedButton46->Glyph->LoadFromResourceName(0, "gl46");
377  SpeedButton47->Glyph->LoadFromResourceName(0, "gl47");
378  SpeedButton48->Glyph->LoadFromResourceName(0, "gl48");
379  SpeedButton49->Glyph->LoadFromResourceName(0, "gl49");
380  SpeedButton50->Glyph->LoadFromResourceName(0, "gl50");
381  SpeedButton51->Glyph->LoadFromResourceName(0, "gl51");
382  SpeedButton52->Glyph->LoadFromResourceName(0, "gl52");
383  SpeedButton53->Glyph->LoadFromResourceName(0, "gl53");
384  SpeedButton54->Glyph->LoadFromResourceName(0, "gl54");
385  SpeedButton55->Glyph->LoadFromResourceName(0, "gl55");
386  SpeedButton56->Glyph->LoadFromResourceName(0, "gl56");
387  SpeedButton57->Glyph->LoadFromResourceName(0, "gl57");
388  SpeedButton58->Glyph->LoadFromResourceName(0, "gl58");
389  SpeedButton59->Glyph->LoadFromResourceName(0, "gl59");
390  SpeedButton60->Glyph->LoadFromResourceName(0, "gl60");
391  SpeedButton61->Glyph->LoadFromResourceName(0, "gl61");
392  SpeedButton62->Glyph->LoadFromResourceName(0, "gl62");
393  SpeedButton63->Glyph->LoadFromResourceName(0, "gl63");
394  SpeedButton64->Glyph->LoadFromResourceName(0, "gl64");
395  SpeedButton65->Glyph->LoadFromResourceName(0, "gl65");
396  SpeedButton66->Glyph->LoadFromResourceName(0, "gl66");
397  SpeedButton67->Glyph->LoadFromResourceName(0, "gl67");
398  SpeedButton68->Glyph->LoadFromResourceName(0, "gl68");
399  SpeedButton69->Glyph->LoadFromResourceName(0, "gl69");
400  SpeedButton70->Glyph->LoadFromResourceName(0, "gl70");
401  SpeedButton71->Glyph->LoadFromResourceName(0, "gl71");
402  SpeedButton72->Glyph->LoadFromResourceName(0, "gl72");
403  SpeedButton73->Glyph->LoadFromResourceName(0, "gl73");
404  SpeedButton74->Glyph->LoadFromResourceName(0, "gl74");
405  SpeedButton75->Glyph->LoadFromResourceName(0, "gl75");
406  SpeedButton76->Glyph->LoadFromResourceName(0, "gl76");
407  SpeedButton77->Glyph->LoadFromResourceName(0, "gl77");
408  SpeedButton78->Glyph->LoadFromResourceName(0, "gl78");
409  SpeedButton79->Glyph->LoadFromResourceName(0, "gl79");
410  SpeedButton80->Glyph->LoadFromResourceName(0, "gl80");
411  SpeedButton81->Glyph->LoadFromResourceName(0, "gl81");
412  SpeedButton82->Glyph->LoadFromResourceName(0, "gl82");
413  SpeedButton83->Glyph->LoadFromResourceName(0, "gl83");
414  SpeedButton84->Glyph->LoadFromResourceName(0, "gl84");
415  SpeedButton85->Glyph->LoadFromResourceName(0, "gl85");
416  SpeedButton86->Glyph->LoadFromResourceName(0, "gl86");
417  SpeedButton87->Glyph->LoadFromResourceName(0, "gl87");
418  SpeedButton88->Glyph->LoadFromResourceName(0, "gl88set");
419  SpeedButton89->Glyph->LoadFromResourceName(0, "gl89set");
420  SpeedButton90->Glyph->LoadFromResourceName(0, "gl90set");
421  SpeedButton91->Glyph->LoadFromResourceName(0, "gl91set");
422  SpeedButton92->Glyph->LoadFromResourceName(0, "gl92set");
423  SpeedButton93->Glyph->LoadFromResourceName(0, "gl93set");
424  SpeedButton94->Glyph->LoadFromResourceName(0, "gl94set");
425  SpeedButton95->Glyph->LoadFromResourceName(0, "gl95set");
426  SpeedButton96->Glyph->LoadFromResourceName(0, "ConcourseGlyph");
427  SpeedButton97->Glyph->LoadFromResourceName(0, "gl97");
428  SpeedButton98->Glyph->LoadFromResourceName(0, "gl98");
429  SpeedButton99->Glyph->LoadFromResourceName(0, "gl99");
430  SpeedButton100->Glyph->LoadFromResourceName(0, "gl100");
431  SpeedButton101->Glyph->LoadFromResourceName(0, "gl101");
432  SpeedButton102->Glyph->LoadFromResourceName(0, "gl102");
433  SpeedButton103->Glyph->LoadFromResourceName(0, "gl103");
434  SpeedButton104->Glyph->LoadFromResourceName(0, "gl104");
435  SpeedButton105->Glyph->LoadFromResourceName(0, "gl105");
436  SpeedButton106->Glyph->LoadFromResourceName(0, "gl106");
437  SpeedButton107->Glyph->LoadFromResourceName(0, "gl107");
438  SpeedButton108->Glyph->LoadFromResourceName(0, "gl108");
439  SpeedButton109->Glyph->LoadFromResourceName(0, "gl109");
440  SpeedButton110->Glyph->LoadFromResourceName(0, "gl110");
441  SpeedButton111->Glyph->LoadFromResourceName(0, "gl111");
442  SpeedButton112->Glyph->LoadFromResourceName(0, "gl112");
443  SpeedButton113->Glyph->LoadFromResourceName(0, "gl113");
444  SpeedButton114->Glyph->LoadFromResourceName(0, "gl114");
445  SpeedButton115->Glyph->LoadFromResourceName(0, "gl115");
446  SpeedButton116->Glyph->LoadFromResourceName(0, "gl116");
447  SpeedButton117->Glyph->LoadFromResourceName(0, "gl117");
448  SpeedButton118->Glyph->LoadFromResourceName(0, "gl118");
449  SpeedButton119->Glyph->LoadFromResourceName(0, "gl119");
450  SpeedButton120->Glyph->LoadFromResourceName(0, "gl120");
451  SpeedButton121->Glyph->LoadFromResourceName(0, "gl121");
452  SpeedButton122->Glyph->LoadFromResourceName(0, "gl122");
453  SpeedButton123->Glyph->LoadFromResourceName(0, "gl123");
454  SpeedButton124->Glyph->LoadFromResourceName(0, "gl124");
455  SpeedButton125->Glyph->LoadFromResourceName(0, "gl125");
456  SpeedButton126->Glyph->LoadFromResourceName(0, "gl126");
457  SpeedButton127->Glyph->LoadFromResourceName(0, "gl127");
458  SpeedButton128->Glyph->LoadFromResourceName(0, "gl128");
459  SpeedButton129->Glyph->LoadFromResourceName(0, "gl129");
460  SpeedButton130->Glyph->LoadFromResourceName(0, "gl130");
461  SpeedButton131->Glyph->LoadFromResourceName(0, "gl131");
462  SpeedButton132->Glyph->LoadFromResourceName(0, "gl132");
463  SpeedButton133->Glyph->LoadFromResourceName(0, "gl133");
464  SpeedButton134->Glyph->LoadFromResourceName(0, "gl134");
465  SpeedButton135->Glyph->LoadFromResourceName(0, "gl135");
466  SpeedButton136->Glyph->LoadFromResourceName(0, "gl136");
467  SpeedButton137->Glyph->LoadFromResourceName(0, "gl137");
468  SpeedButton138->Glyph->LoadFromResourceName(0, "gl138");
469  SpeedButton139->Glyph->LoadFromResourceName(0, "gl139");
470  SpeedButton140->Glyph->LoadFromResourceName(0, "gl140");
471  SpeedButton141->Glyph->LoadFromResourceName(0, "gl141");
472  SpeedButton142->Glyph->LoadFromResourceName(0, "gl142");
473  SpeedButton143->Glyph->LoadFromResourceName(0, "gl143");
474  SpeedButton145->Glyph->LoadFromResourceName(0, "gl145");
475  SpeedButton146->Glyph->LoadFromResourceName(0, "gl146");
476  // below not in RailGraphics
477  SpeedButton144->Glyph->LoadFromResourceName(0, "LCGlyph");
478 
479  AddPrefDirButton->Glyph->LoadFromResourceName(0, "AddPrefDir");
480  AddTextButton->Glyph->LoadFromResourceName(0, "AddText");
481  AddTrackButton->Glyph->LoadFromResourceName(0, "AddTrack");
482  AutoSigsButton->Glyph->LoadFromResourceName(0, "AutoSig");
483  CallingOnButton->Glyph->LoadFromResourceName(0, "CallingOn");
484  DeleteAllPrefDirButton->Glyph->LoadFromResourceName(0, "ClearAllPrefDir");
485  DeleteOnePrefDirButton->Glyph->LoadFromResourceName(0, "ClearOnePrefDir");
486  ExitOperationButton->Glyph->LoadFromResourceName(0, "Exit");
487  ExitPrefDirButton->Glyph->LoadFromResourceName(0, "Exit");
488  ExitTrackButton->Glyph->LoadFromResourceName(0, "Exit");
489  ExitTTModeButton->Glyph->LoadFromResourceName(0, "Exit");
490  FontButton->Glyph->LoadFromResourceName(0, "FontGraphic");
491  HomeButton->Glyph->LoadFromResourceName(0, "Home");
492  LocationNameButton->Glyph->LoadFromResourceName(0, "NameLocs");
493  MoveTextOrGraphicButton->Glyph->LoadFromResourceName(0, "MoveTextOrGraphic");
494  NewHomeButton->Glyph->LoadFromResourceName(0, "NewHome");
495  UnrestrictedButton->Glyph->LoadFromResourceName(0, "NonSig");
496  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
497  OperatorActionButton->Glyph->LoadFromResourceName(0, "ShowOpActionPanel");
498  PerformanceLogButton->Glyph->LoadFromResourceName(0, "ShowLog");
499  PresetAutoSigRoutesButton->Glyph->LoadFromResourceName(0, "PresetAutoSigRoutes");
500  RouteCancelButton->Glyph->LoadFromResourceName(0, "RouteCancel");
501  SaveRailwayPDPButton->Glyph->LoadFromResourceName(0, "SaveRailway"); // PrefDirPanel
502  SaveRailwayBaseModeButton->Glyph->LoadFromResourceName(0, "SaveRailway"); // OperatingPanel
503  SaveRailwayTBPButton->Glyph->LoadFromResourceName(0, "SaveRailway"); // TrackBuildPanel
504  SaveSessionButton->Glyph->LoadFromResourceName(0, "SaveSession");
505  ScreenDownButton->Glyph->LoadFromResourceName(0, "BlackArrowDown");
506  ScreenGridButton->Glyph->LoadFromResourceName(0, "ScreenGrid");
507  ScreenLeftButton->Glyph->LoadFromResourceName(0, "BlackArrowLeft");
508  ScreenRightButton->Glyph->LoadFromResourceName(0, "BlackArrowRight");
509  ScreenUpButton->Glyph->LoadFromResourceName(0, "BlackArrowUp");
510  SetGapsButton->Glyph->LoadFromResourceName(0, "ConnectGaps");
511  SetLengthsButton->Glyph->LoadFromResourceName(0, "SetDists");
512  ShowHideTTButton->Glyph->LoadFromResourceName(0, "Hide");
513  SigAspectButton->Glyph->LoadFromResourceName(0, "FourAspect"); // new at version 0.6
514  SigPrefButton->Glyph->LoadFromResourceName(0, "PrefSig");
515  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision1");
516  TrackOKButton->Glyph->LoadFromResourceName(0, "Validate");
517  TTClockAdjButton->Glyph->LoadFromResourceName(0, "TTClock");
518  UserGraphicButton->Glyph->LoadFromResourceName(0, "PictureImage");
519 
520  BufferAttentionImage->Picture->Bitmap->LoadFromResourceName(0, "BufferWarning");
521  CallOnImage->Picture->Bitmap->LoadFromResourceName(0, "CallingOn");
522  CrashImage->Picture->Bitmap->LoadFromResourceName(0, "CrashWarning");
523  DerailImage->Picture->Bitmap->LoadFromResourceName(0, "DerailWarning");
524  SignalStopImage->Picture->Bitmap->LoadFromResourceName(0, "SignalStopWarning");
525  SPADImage->Picture->Bitmap->LoadFromResourceName(0, "SPADWarning");
526  TrainFailedImage->Picture->Bitmap->LoadFromResourceName(0, "TrainFailedWarning"); // new at v2.4.0
527 
528  DistanceKey->Picture->Bitmap->LoadFromResourceName(0, "DistanceKey");
529  PrefDirKey->Picture->Bitmap->LoadFromResourceName(0, "PrefDirKey");
530 
531  TrackLinkedImage->Picture->Bitmap->LoadFromResourceName(0, "TrackLinkedGraphic");
532  TrackNotLinkedImage->Picture->Bitmap->LoadFromResourceName(0, "TrackNotLinkedGraphic");
533  GapsNotSetImage->Picture->Bitmap->LoadFromResourceName(0, "GapsNotSetGraphic");
534  GapsSetImage->Picture->Bitmap->LoadFromResourceName(0, "GapsSetGraphic");
535  LocationNamesNotSetImage->Picture->Bitmap->LoadFromResourceName(0, "LocNamesNotSetGraphic");
536  LocationNamesSetImage->Picture->Bitmap->LoadFromResourceName(0, "LocNamesSetGraphic");
537 
538 /* Don't need this - load icon directly into both Interface form & Application (via Project - Options - Application - Load Icon)
539  RailwayIcon = new TPicture;
540  RailwayIcon->Icon->LoadFromResourceName(0, "Icon1.ico");
541  Icon = RailwayIcon->Icon;
542  Application->Icon = RailwayIcon->Icon;
543 */
544 
545  AnsiString NL = '\n';
546  const AnsiString TTLabelStr1 = "Start new train" + NL + "Start new service from a split" + NL + "Start new service from another service" + NL +
547  "Start new non-repeating shuttle finish service" + NL + "Start new shuttle train at a timetabled stop" + NL +
548  "Start new shuttle service from a feeder";
549 
550  const AnsiString TTLabelStr2 = "Pass" + NL + "Be joined by another train" + NL + "Front split" + NL + "Rear split" + NL + "Change direction of train";
551 
552  const AnsiString TTLabelStr3 = "Finish && form a new service" + NL + "Finish && join another train" + NL + "Finish && exit railway" + NL +
553  "Finish && repeat shuttle, finally remain here" + NL + "Finish && repeat shuttle, finally form a finishing service" + NL +
554  "Finish non-repeating shuttle feeder service" + NL + "Finish && remain here";
555 
556  const AnsiString TTLabelStr4 = "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL +
557  "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + "HH:MM" + NL + " " + NL + "R";
558 
559  const AnsiString TTLabelStr5 = "HH:MM ';' Location" + NL + "HH:MM ';' HH:MM ';' Location";
560 
561  const AnsiString TTLabelStr6 = "+ rear element ID - space - front element ID [+ optional ';S']" + NL + "+ ref. of the train that splits" + NL +
562  "+ other service ref." + NL + "+ shuttle service ref." + NL + "+ rear element ID - space - front element ID ';' linked shuttle ref." + NL +
563  "+ linked shuttle service ref. ';' feeder service ref." + NL + "+ location" + NL + "+ joining train ref." + NL + "+ new service ref." + NL +
564  "+ new service ref." + NL + " " + NL + "+ new service ref." + NL + "+ ref. of train to join" + NL +
565  "+ list of valid exit element IDs (at least 1) separated by spaces" + NL + "+ linked shuttle service ref.";
566 
567  const AnsiString TTLabelStr7 = "Arrival OR departure time (program will determine which from the context) + location." + NL +
568  "Arrival time, departure time (with no events between) + location";
569 
570  const AnsiString TTLabelStr9 = "Timetable entries" + NL + "(service references etc.)";
571  const AnsiString TTLabelStr11 = "Timetable" + NL + "start time";
572 
573  const AnsiString TTLabelStr12 = "NB: WITHIN SERVICES commas must" + NL + "not be used (have special meanings)," + NL +
574  "and semicolons may only be used to" + NL + "separate service components.";
575 
576  const AnsiString TTLabelStr13 = "+ linked shuttle service ref. ';' finishing service ref." + NL + "+ linked shuttle service ref.";
577 
578  const AnsiString TTLabelStr15 = "Repeat the service + ';' minutes between repeats ';' digit increment ';' number of repeats (last line of service)";
579 
580  TTLabel1->Caption = TTLabelStr1;
581  TTLabel2->Caption = TTLabelStr2;
582  TTLabel3->Caption = TTLabelStr3;
583  TTLabel4->Caption = TTLabelStr4;
584  TTLabel5->Caption = TTLabelStr5;
585  TTLabel6->Caption = TTLabelStr6;
586  TTLabel7->Caption = TTLabelStr7;
587  TTLabel9->Caption = TTLabelStr9;
588  TTLabel11->Caption = TTLabelStr11;
589  TTLabel12->Caption = TTLabelStr12;
590  TTLabel13->Caption = TTLabelStr13;
591  TTLabel15->Caption = TTLabelStr15;
592 
593  SelectBitmap->TransparentColor = Utilities->clTransparent;
594  RailGraphics->ChangeAllTransparentColours(Utilities->clTransparent, clB5G5R5); // original colour is as loaded at this stage - white
596 
597  TextBox->Color = clB3G3R3;
598  MainScreen->Canvas->Brush->Color = Utilities->clTransparent;
599  MainScreen->Canvas->FillRect(MainScreen->ClientRect);
600 
601  if((Screen->Width < 1024) || (Screen->Height < 768))
602  {
603  ShowMessage("Please note that this program works best with a screen resolution of at least 1024 x 768. Please change if possible");
604  }
605 
606  SkipFormResizeEvent = true; // added at v2.1.0
607  MasterClock->Enabled = true;
608  Visible = true; // make Interface form visible (set to false at design time) autocalls FormResize so it is skipped
609  WindowState = wsMaximized; // need this for full screen at start autocalls FormResize so it is skipped
610  MTBFEditBox->Left = MainScreen->Left + MainScreen->Width - MTBFEditBox->Width + 30; // new v2.4.0 30 is to place it above the positional panel
611  // has to come after Visible = true or doesn't show
612  MTBFLabel->Left = MainScreen->Left + MainScreen->Width - MTBFEditBox->Width + 30 - 55; // new v2.4.0 placed above and to the left of MTBFEditBox
613  PositionalPanel->Left = MainScreen->Left + MainScreen->Width; // changed at v2.4.0
614  PositionalPanel->Top = MainScreen->Top; // changed at v2.4.0
615  PositionalPanel->Height = MainScreen->Height; // changed at v2.4.0
616  AllSetUpFlag = true;
617  MissedTicks = 0;
618  TotalTicks = 0;
620  SetLevel1Mode(131); // to reset background colour mode menu choices
621  Screen->Cursor = TCursor(-2); // Arrow
622  SkipFormResizeEvent = false; // added at v2.1.0
623  SelectedGraphicFileName = ""; // only set to null here so always has a value after use LoadUserGraphic
624 
625  FloatingPanel->Color = TColor(0xF0FFFF); // new v2.2.0, corrects floating panel background colour in Windows 10
626  PerformancePanel->Color = TColor(0xCCCCCC); // new v2.2.0 as above
627  OperatorActionPanel->Color = TColor(0xCCCCCC); // new v2.2.0 as above
628  DevelopmentPanel->Color = TColor(0xCCCCCC); // new v2.2.0 as above
629  TTStartTimeBox->Color = TColor(0x99FFFF); // cream
630  HighlightPanel->Color = TColor(0x33CCFF);
632  MTBFEditBox->Visible = false; // new at v2.4.0
633  MTBFLabel->Visible = false;
637  TTStartTimePtr = 0;
638  TTFirstServicePtr = 0;
639  TTLastServicePtr = 0;
640  Track->OverrideAndHideSignalBridgeMessage = false; //added at v2.5.1 to allow facing signals before bridges - with a warning
641  ConflictPanel->Visible = false;
642  TTClockAdjustWarningPanel->Visible = false;
643  TTClockAdjustWarningHide = false;
644  LastNonCtrlOrShiftKeyDown = -1; //set to no key
645 
646  SigImagePanel->Left = (Interface->Width - SigImagePanel->Width) / 2; // added for v2.3.0
647 
648  // below added at v2.4.0 so able to load session files with the correct decimal point
649  Utilities->DecimalPoint = '.'; // default case is full stop
650  char *LocalNumericInformation = setlocale(LC_NUMERIC, ""); // need this to set lconv to the environment's numeric format
652  if(LocalNumericInformation == "") // call failed, don't change decimal point in Utilities.cpp
653  {
654  Utilities->SetLocaleResultOK = false;
655  }
656  struct lconv Locale; // store this structure in memory (accessed via locale.h in Utilities.h)
657  struct lconv *conv = &Locale;
658  // read the locality conversion structure
659  conv = localeconv(); // this is what updates the structure
660  Utilities->DecimalPoint = conv->decimal_point[0];
661  }
662 
663  catch(const EFOpenError &e)
664  {
665  TMsgDlgButtons But;
666  But << mbOK;
667  MessageDlg(e.Message + " - program must terminate", mtError, But, 0);
668  Application->Terminate();
669  }
670 
671  catch(const Exception &e)
672  {
673  TMsgDlgButtons But;
674  But << mbOK;
675  AnsiString Message = "A fatal error occurred during the program setup process, the program must terminate. Message = " + e.Message;
676  MessageDlg(Message, mtError, But, 0); // this message given first in case can't create the error log
677  ErrorLog(115, e.Message);
678  Application->Terminate();
679  }
680 }
681 
682 // ---------------------------------------------------------------------------
683 
685 { // destructor
686  try
687  {
688  //rewrite ConfigFile with signal handedness, background colour & InitialDir values (may be same but no matter)
689  AnsiString ColourStr = "", SignalStr = "";
690  remove((CurDir + "\\Config.txt").c_str());
691  std::ofstream ConfigFile((CurDir + "\\Config.txt").c_str());
692  ColourStr = "black";
693  SignalStr = "left";
694  if(Utilities->clTransparent == TColor(0xFFFFFF))
695  {
696  ColourStr = "white";
697  }
698  else if(Utilities->clTransparent == TColor(0x330000))
699  {
700  ColourStr = "blue";
701  }
703  {
704  SignalStr = "right";
705  }
706 
707  ConfigFile << AnsiString("Signals=") << SignalStr << '\n';
708  ConfigFile << AnsiString("BgndCol=") << ColourStr << '\n';
709  ConfigFile << AnsiString("RLYLocn=") << AnsiString(LoadRailwayDialog->InitialDir) << '\n';
710  ConfigFile << AnsiString("TTBLocn=") << AnsiString(TimetableDialog->InitialDir) << '\n';
711  ConfigFile << AnsiString("SSNLocn=") << AnsiString(LoadSessionDialog->InitialDir) << '\n';
712  ConfigFile.close();
713 
714  SkipFormResizeEvent = true; // added at v2.1.0
715  delete NonSigRouteStartMarker;
716  delete SigRouteStartMarker;
717  delete AutoRouteStartMarker;
718  delete PointFlash;
719  delete SelectBitmap;
720  delete TrainController;
721  delete EveryPrefDir;
722  delete ConstructRoute;
723  delete ConstructPrefDir;
724  delete AllRoutes;
725  delete Track;
726  delete TextHandler;
727  delete HiddenDisplay;
728  delete HiddenScreen;
729  delete Display;
730  delete RailGraphics;
731  delete Utilities;
732  DeleteFile(TempTTFileName); //added after v2.4.3 to prevent temporary files building up
733  }
734  catch(const Exception &e)
735  {
736  ErrorLog(116, e.Message);
737  }
738 }
740 
741 // ---------------------------------------------------------------------------
742 
743 void __fastcall TInterface::FormCreate(TObject *Sender)
744 { // these functions have to be defined here to take effect when application activated & deactivated
745  try
746  {
747  Application->OnDeactivate = AppDeactivate;
748  Application->OnActivate = AppActivate;
749  }
750  catch(const Exception &e)
751  {
752  ErrorLog(117, e.Message);
753  }
754 }
755 
756 // ---------------------------------------------------------------------------
757 
758 void __fastcall TInterface::AppDeactivate(TObject *Sender)
759 { // pause operation if operating & stop the master clock
760  try
761  {
763  {
764  if(Track->RouteFlashFlag) // in case route building - cancels the route, freezes otherwise - reported
765  { // by Matt Blades 30/06/11
769  Screen->Cursor = TCursor(-2); // Arrow
770  Track->RouteFlashFlag = false;
771  ClearandRebuildRailway(48); // to get rid of displayed route
772  }
773  if(Track->PointFlashFlag)
774  // added at v1.3.1 to prevent lockup for flashing points when deactivates. Notified by Ian Walker in his email of 25/03/13.
775  {
777  Track->PointFlashFlag = false;
779  Screen->Cursor = TCursor(-2); // Arrow
780  }
783  }
784  MasterClock->Enabled = false;
785  }
786  catch(const Exception &e)
787  {
788  ErrorLog(118, e.Message);
789  }
790 }
791 
792 // ---------------------------------------------------------------------------
793 
794 void __fastcall TInterface::AppActivate(TObject *Sender)
795 { // restart the master clock providing Interface constructor has run
796  try
797  {
798  if(AllSetUpFlag)
799  {
800  MasterClock->Enabled = true;
801  }
802  }
803  catch(const Exception &e)
804  {
805  ErrorLog(119, e.Message);
806  }
807 }
808 
809 // ---------------------------------------------------------------------------
810 
811 UnicodeString TInterface::GetVersion()
812 {
813  DWORD VersionHandle;
814  DWORD VersionSize;
815  LPBYTE pBuffer;
816  UnicodeString strVersion = L"N/A";
817 
818  VersionSize = GetFileVersionInfoSizeW(Application->ExeName.c_str(), &VersionHandle);
819  if(VersionSize)
820  {
821  pBuffer = new BYTE[VersionSize];
822 
823  if(GetFileVersionInfoW(Application->ExeName.c_str(), VersionHandle, VersionSize, pBuffer))
824  {
825  VS_FIXEDFILEINFO *fi;
826  UINT buflen;
827 
828  // uncomment strVersion and HIWORD alternates below when future CI implemented: sas@2.1.0
829  if(VerQueryValueW(pBuffer, L"\\", (void**)&fi, &buflen))
830  {
831  // strVersion.sprintf(L"%d.%d.%d (Build %d)",
832  strVersion.sprintf(L"%d.%d.%d", HIWORD(fi->dwFileVersionMS), LOWORD(fi->dwFileVersionMS), HIWORD(fi->dwFileVersionLS)
833  // HIWORD(fi->dwFileVersionLS), LOWORD(fi->dwFileVersionLS)
834  );
835  }
836  }
837 
838  delete[]pBuffer;
839  }
840 
841  return L" v" + strVersion;
842 }
843 
844 // ---------------------------------------------------------------------------
845 // Track Build Interface
846 // ---------------------------------------------------------------------------
847 void __fastcall TInterface::BuildTrackMenuItemClick(TObject *Sender) // Mode Menu Item
848 {
849  try
850  {
851  TrainController->LogEvent("BuildTrackMenuItemClick");
852  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",BuildTrackMenuItemClick");
854  SetLevel1Mode(0);
855  Utilities->CallLogPop(1159);
856  }
857  catch(const Exception &e)
858  {
859  ErrorLog(120, e.Message);
860  }
861 }
862 // ---------------------------------------------------------------------------
863 
864 void __fastcall TInterface::AddTrackButtonClick(TObject *Sender)
865 {
866  try
867  {
868  TrainController->LogEvent("AddTrackButtonClick");
869  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AddTrackButtonClick");
871  SetLevel1Mode(38);
874  Utilities->CallLogPop(1162);
875  }
876  catch(const Exception &e)
877  {
878  ErrorLog(121, e.Message);
879  }
880 }
881 
882 // ---------------------------------------------------------------------------
883 void __fastcall TInterface::SpeedButtonClick(TObject *Sender)
884 {
885  try
886  {
887  TrainController->LogEvent("SpeedButtonClick");
888  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SpeedButtonClick");
889  ReselectMenuItem->Enabled = false;
890  if(((TSpeedButton*)Sender)->Down)
891  {
892  CurrentSpeedButton = (TSpeedButton*)Sender;
893 // TrainController->LogEvent("SpeedButtonClick, " + CurrentSpeedButton->Tag); //v 1.3.1 - using non-AnsiString CurrentSpeedButton->Tag sends (for an unknown reason) a completely wrong string to LogEvent, usually "...(behind this message)"
894  TrainController->LogEvent("SpeedButtonClick, " + AnsiString(CurrentSpeedButton->Tag)); // new version //use for v1.3.2
895  if((Level2TrackMode == TrackSelecting) && (CurrentSpeedButton->Tag != 144)) //new addition at v2.6.0 to fill selected area with the element corresponding to CurrentSpeedButton
896  { //144 = level crossing & these not permitted
897  if((SelectRect.left != SelectRect.right) && (SelectRect.top != SelectRect.bottom) && SelectionValid)
898  {
899  Screen->Cursor = TCursor(-11); // Hourglass;
900  InfoPanel->Caption = "SELECTING: Filling area with chosen element";
901  bool FillSelectionFlag = false;
903  {
904  UnicodeString MessageStr = "Click 'Yes' to fill the area with the chosen element or 'No' to abort.\n"
905  "Existing elements won't be overwritten although track can\n"
906  "have platforms and non-station named location elements added.\n\nThis message will not be shown again.";
907  int button = Application->MessageBox(MessageStr.c_str(), L"", MB_YESNO);
908  if(button == IDYES)
909  {
910  FillSelectionFlag = true;
911  }
912  }
913  if(FillSelectionFlag || FillSelectionMessageSentFlag)
914  {
915  bool TrackLinkingRequiredFlag = true;
916  for(int HLoc = SelectRect.left; HLoc < SelectRect.right; HLoc++)
917  {
918  for(int VLoc = SelectRect.top; VLoc < SelectRect.bottom; VLoc++)
919  {
920  if((HLoc != SelectRect.right) || (VLoc != SelectRect.bottom))
921  {
922  Track->PlotAndAddTrackElement(3, CurrentSpeedButton->Tag, 0, HLoc, VLoc, TrackLinkingRequiredFlag, false); //false for internal checks
923  // above now has extra zero 'Aspect' parameter at v2.2.0 so can distinguish between adding track and pasting
924  }
925  else
926  {
927  Track->PlotAndAddTrackElement(4, CurrentSpeedButton->Tag, 0, HLoc, VLoc, TrackLinkingRequiredFlag, true); //internal checks true for last plot
928  }
929  }
930  }
931  }
932  Track->SetTrackFinished(false);
933  ClearandRebuildRailway(80); // to remove selection outline
934  SelectionValid = false;
935  Track->CopyFlag = false;
937  ResetSelectRect();
938  SetLevel1Mode(139);
940  SetLevel2TrackMode(66);
942  Screen->Cursor = TCursor(-2); // Arrow
943  ReselectMenuItem->Enabled = true; //allow when filling areas
944  }
945  }
946  }
947  else
948  {
949  CurrentSpeedButton = 0;
950  }
951  Utilities->CallLogPop(1163);
952  }
953  catch(const Exception &e)
954  {
955  ErrorLog(122, e.Message);
956  }
957 }
958 
959 // ---------------------------------------------------------------------------
960 void __fastcall TInterface::TrackOKButtonClick(TObject *Sender)
961 {
962  try
963  {
964  TrainController->LogEvent("TrackOKButtonClick");
965  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TrackOKButtonClick");
966  SelectionValid = false;
968  bool LocError;
969  int HLoc, VLoc;
970  // erase any corrupted PrefDirs then rebuild track & PrefDir vectors
971 // EveryPrefDir->EraseCorruptedElementsAfterTrackBuild(); not needed after dispensed with blank track elements for erased elements
972  if(!(Track->TryToConnectTrack(0, LocError, HLoc, VLoc, true))) // true for give messages
973  // if successful repositions TrackVector & builds TrackMap
974  {
975  if(LocError) // links not complete or other error - show offending element
976  {
977  while((Display->DisplayOffsetH - HLoc) > 0)
978  Display->DisplayOffsetH -= (Utilities->ScreenElementWidth / 2); // use 30 instead of 60 so less likely to appear behind the message box
979  while((HLoc - Display->DisplayOffsetH) > (Utilities->ScreenElementWidth - 1))
981  while((Display->DisplayOffsetV - VLoc) > 0)
982  Display->DisplayOffsetV -= (Utilities->ScreenElementHeight / 2); // use 18 instead of 36 so less likely to appear behind the message box
983  while((VLoc - Display->DisplayOffsetV) > (Utilities->ScreenElementHeight - 1))
986  Display->InvertElement(0, HLoc * 16, VLoc * 16);
987  ShowMessage("Incomplete track or other error - see inverted element (may be behind this message)");
988  ClearandRebuildRailway(1); // to clear inversion
990  SetLevel1Mode(39);
991  Level2TrackMode = AddTrack; // go to add track regardless of where started from
993  Utilities->CallLogPop(0);
994  return;
995  }
996  else
997  { // reach here if there are no track elements
998  ShowMessage("Unable to set any track links");
1000  SetLevel1Mode(40);
1002  SetLevel2TrackMode(4); // go to add track regardless of where started from
1003  Utilities->CallLogPop(1);
1004  return;
1005  }
1006  }
1007  else
1008  {
1009  // success ('TrackFinished' set in TryToConnectTrack)
1010  EveryPrefDir->RebuildPrefDirVector(0); // from TrackMap
1011  ShowMessage("Successful Completion");
1012  }
1013 // success if reach here ('TrackFinished' set in TryToConnectTrack)
1014  if(Level2TrackMode == AddTrack)
1015  {
1017  SetLevel1Mode(41);
1018  SetLevel2TrackMode(5);
1019  }
1020  else
1021  {
1023  SetLevel1Mode(36); // back to TrackMode if not in AddTrack mode
1024  }
1025  Utilities->CallLogPop(2);
1026  }
1027  catch(const Exception &e)
1028  {
1029  ErrorLog(3, e.Message);
1030  }
1031 }
1032 
1033 // ---------------------------------------------------------------------------
1034 void __fastcall TInterface::SetGapsButtonClick(TObject *Sender)
1035 {
1036  try
1037  {
1038  TrainController->LogEvent("SetGapsButtonClick");
1039  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SetGapsButtonClick");
1040  SelectionValid = false;
1041  ReselectMenuItem->Enabled = false;
1043  SetLevel1Mode(42);
1045  SetLevel2TrackMode(6);
1046  Utilities->CallLogPop(1164);
1047  }
1048  catch(const Exception &e)
1049  {
1050  ErrorLog(123, e.Message);
1051  }
1052 }
1053 
1054 // ---------------------------------------------------------------------------
1055 void __fastcall TInterface::AddTextButtonClick(TObject *Sender)
1056 {
1057  try
1058  {
1059  TrainController->LogEvent("AddTextButtonClick");
1060  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AddTextButtonClick");
1062  SetLevel1Mode(43);
1064  SetLevel2TrackMode(7);
1065  Utilities->CallLogPop(1165);
1066  }
1067  catch(const Exception &e)
1068  {
1069  ErrorLog(124, e.Message);
1070  }
1071 }
1072 
1073 // ---------------------------------------------------------------------------
1074 void __fastcall TInterface::MoveTextOrGraphicButtonClick(TObject *Sender)
1075 {
1076  try
1077  {
1078  TrainController->LogEvent("MoveTextOrGraphicButtonClick");
1079  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MoveTextOrGraphicButtonClick");
1081  SetLevel1Mode(44);
1083  SetLevel2TrackMode(8);
1084  Utilities->CallLogPop(1166);
1085  }
1086  catch(const Exception &e)
1087  {
1088  ErrorLog(125, e.Message);
1089  }
1090 }
1091 
1092 // ---------------------------------------------------------------------------
1093 void __fastcall TInterface::TextBoxKeyPress(TObject *Sender, char &Key)
1094 {
1095  try
1096  {
1097  TrainController->LogEvent("TextBoxKeyPress," + AnsiString(Key));
1098  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TextBoxKeyPress," + AnsiString(Key));
1099  if(Key == '\x0D') // CR
1100  {
1101  if(TextBox->Text != "") // if blank then don't save
1102  {
1103  if(Display->GetFont()->Color == clB5G5R5) // white
1104  {
1105  TFont *TempFont = new TFont;
1106  TempFont->Assign(Display->GetFont());
1107  TempFont->Color = clB0G0R0; // change to black for vector & saving
1108  Display->SetFont(TempFont);
1109  delete TempFont;
1110  }
1111  TFont *DisplayFont = Display->GetFont();
1112  TTextItem TempText = TTextItem(Text_X, Text_Y, TextBox->Text, DisplayFont);
1113  TempText.Font = DisplayFont; // may have been changed in above constructor when returned as reference
1115  }
1116  EditMenu->Enabled = true;
1117  TextBox->Visible = false;
1118  SetLevel2TrackMode(56); // to enable 'move text' if first text item added
1119  }
1120  else if(Key == '\x1B') // escape
1121  {
1122  TextBox->Visible = false;
1123  }
1124  Utilities->CallLogPop(3);
1125  }
1126  catch(const Exception &e)
1127  {
1128  ErrorLog(4, e.Message);
1129  }
1130 }
1131 
1132 // ---------------------------------------------------------------------------
1133 void __fastcall TInterface::LocationNameButtonClick(TObject *Sender)
1134 {
1135  try
1136  {
1137  TrainController->LogEvent("LocationNameButtonClick");
1138  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LocationNameButtonClick");
1140  SetLevel1Mode(45);
1142  SetLevel2TrackMode(9);
1143  Utilities->CallLogPop(1167);
1144  }
1145  catch(const Exception &e)
1146  {
1147  ErrorLog(126, e.Message);
1148  }
1149 }
1150 
1151 // ---------------------------------------------------------------------------
1152 void __fastcall TInterface::LocationNameKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
1153 {
1154  try
1155  {
1156  TrainController->LogEvent("LocationNameKeyUp," + AnsiString(Key));
1157  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LocationNameKeyUp," + AnsiString(Key));
1158  if(Track->LNPendingList.empty())
1159  {
1160  ShowMessage("Error, location name being entered without an entry in LNPendingList");
1162  SetLevel1Mode(46);
1164  SetLevel2TrackMode(10);
1165  Utilities->CallLogPop(4);
1166  return;
1167  }
1168  if(Key == '\x1B') // escape
1169  {
1170  Track->LNPendingList.clear(); // get rid of existing entry
1172  SetLevel1Mode(47);
1174  SetLevel2TrackMode(11);
1175  Utilities->CallLogPop(5);
1176  return;
1177  }
1178  if(Key == '\x0D')
1179  {
1180  Screen->Cursor = TCursor(-11); // Hourglass;
1182  AnsiString ExistingName;
1183  LocationNameTextBox->Text = LocationNameTextBox->Text.Trim(); //added at v2.6.1 to prevent added spaces because they skip the different location same name chack
1184  if(Track->LNPendingList.front() > -1)
1185  ExistingName = Track->InactiveTrackElementAt(27, Track->LNPendingList.front()).LocationName;
1186  else
1187  ExistingName = Track->TrackElementAt(425, -1 - (Track->LNPendingList.front())).LocationName;
1188  if(Track->LocationNameAllocated(1, LocationNameTextBox->Text) && (ExistingName != LocationNameTextBox->Text))
1189  { // name allocated to a different location
1190  UnicodeString MessageStr = UnicodeString("Another location named '") + LocationNameTextBox->Text +
1191  UnicodeString("' already exists. If you continue its name will be erased. Do you wish to continue?");
1192  int button = Application->MessageBox(MessageStr.c_str(), L"Warning!", MB_YESNO | MB_ICONWARNING);
1193  if(button == IDNO)
1194  {
1195  Track->LNPendingList.clear(); // get rid of existing entry
1196  Screen->Cursor = TCursor(-2); // Arrow
1198  SetLevel1Mode(48);
1200  SetLevel2TrackMode(12);
1201  Utilities->CallLogPop(6);
1202  return;
1203  }
1205  Track->EnterLocationName(1, LocationNameTextBox->Text, false);
1206  int HPos, VPos;
1207  bool UseExistingPosition = false;
1208  if(EraseLocationNameText(0, LocationNameTextBox->Text, HPos, VPos))
1209  {;
1210  } // condition not used
1211  // above may be redundant at v1.1.0 due to name erase in EnterLocationName
1212  // but, the location to be named may also have an existing name, in which case that needs to be erased
1213  // and the position re-used
1214  if(ExistingName != "")
1215  {
1216  if(EraseLocationNameText(3, ExistingName, HPos, VPos))
1217  UseExistingPosition = true; // may be redundant at v1.1.0 due to name erase in EnterLocationName
1218  }
1219  AddLocationNameText(0, LocationNameTextBox->Text, HPos, VPos, UseExistingPosition);
1220  Screen->Cursor = TCursor(-2); // Arrow
1222  SetLevel1Mode(49);
1224  SetLevel2TrackMode(13);
1225  Utilities->CallLogPop(7);
1226  return;
1227  }
1228  else if(Track->LocationNameAllocated(2, LocationNameTextBox->Text) && (ExistingName == LocationNameTextBox->Text))
1229  { // same name being entered again
1230  Track->LNPendingList.clear(); // get rid of existing entry as the location already has this name
1231  // but in case the name is not already in text vector erase it and re-add it
1232  // if it wasn't in the vector erasing it has no effect
1233  int HPos, VPos;
1234  bool UseExistingPosition = false;
1235  if(EraseLocationNameText(2, LocationNameTextBox->Text, HPos, VPos))
1236  UseExistingPosition = true;
1237  // above may be redundant at v1.1.0 due to name erase in EnterLocationName
1238  AddLocationNameText(2, LocationNameTextBox->Text, HPos, VPos, UseExistingPosition);
1239  Screen->Cursor = TCursor(-2); // Arrow
1241  SetLevel1Mode(50);
1243  SetLevel2TrackMode(14);
1244  Utilities->CallLogPop(8);
1245  return;
1246  }
1247  else
1248  { // either a new name for an unnamed location, or a different name for a named location
1249  // check validity of entry
1250  AnsiString LocStr = LocationNameTextBox->Text;
1251  LocStr = LocStr.Trim(); // strip leading & trailing spaces, and control characters
1252  LocationNameTextBox->Text = LocStr; // reset this as used below
1253 /* drop this, now covered by ...Trim() above
1254  //strip leading spaces
1255  while((LocStr != "") && (LocStr[1] == ' '))
1256  {
1257  LocStr = LocStr.SubString(2, LocStr.Length()-1);
1258  }
1259 */
1260  if((LocStr != "") && (LocStr[1] >= '0') && (LocStr[1] <= '9')) // can't begin with a number
1261  {
1262  Screen->Cursor = TCursor(-2); // Arrow
1263  ShowMessage("Location name can't begin with a number");
1265  SetLevel1Mode(51);
1267  SetLevel2TrackMode(15);
1268  Utilities->CallLogPop(776);
1269  return;
1270  }
1271  if(LocStr.Length() > 50)
1272  {
1273  Screen->Cursor = TCursor(-2); // Arrow
1274  ShowMessage("Location name too long, 50 characters maximum");
1276  SetLevel1Mode(122);
1278  SetLevel2TrackMode(55);
1279  Utilities->CallLogPop(1735);
1280  return;
1281  }
1282  for(int x = 1; x <= LocStr.Length(); x++)
1283  {
1284  char Ch = LocStr[x];
1285  if((Ch != ' ') && (Ch != '&') && (Ch != '(') && (Ch != ')') && (Ch != ':') && (Ch != 39) && (Ch != '.') && (Ch != '-') && (Ch != '+') &&
1286  (Ch != '/') && ((Ch < '0') || (Ch > '9')) && ((Ch < 'A') || (Ch > 'Z')) && ((Ch < 'a') || (Ch > 'z')))
1287  {
1288  Screen->Cursor = TCursor(-2); // Arrow
1289  ShowMessage(
1290  "Location name contains one or more invalid characters, must be alphanumeric, brackets, space, full stop, colon, inverted comma, '-', '+', '/' or '&&'");
1292  SetLevel1Mode(52);
1294  SetLevel2TrackMode(16);
1295  Utilities->CallLogPop(777);
1296  return;
1297  }
1298  }
1299  if(LocStr == "cdt") // this has Time:Command which could be confused with Time:Loc
1300  {
1301  Screen->Cursor = TCursor(-2); // Arrow
1302  ShowMessage("Location name cannot be 'cdt', this name would interfere with the timetable");
1304  SetLevel1Mode(53);
1306  SetLevel2TrackMode(17);
1307  Utilities->CallLogPop(778);
1308  return;
1309  }
1310  Track->EnterLocationName(2, LocStr, false);
1311  // need to check if the location already has a name, and if so erase it from the textvector
1312  int HPos, VPos;
1313  bool UseExistingPosition = false;
1314  if(ExistingName != "")
1315  {
1316  if(EraseLocationNameText(1, ExistingName, HPos, VPos))
1317  UseExistingPosition = true; // may be redundant at v1.1.0 due to name erase in EnterLocationName
1318  }
1319  AddLocationNameText(1, LocationNameTextBox->Text, HPos, VPos, UseExistingPosition);
1320  Screen->Cursor = TCursor(-2); // Arrow
1322  SetLevel1Mode(54);
1324  SetLevel2TrackMode(18);
1325  Utilities->CallLogPop(9);
1326  return;
1327  }
1328  }
1329  Screen->Cursor = TCursor(-2); // Arrow
1330  Utilities->CallLogPop(10);
1331  }
1332  catch(const Exception &e)
1333  {
1334  ErrorLog(5, e.Message);
1335  }
1336 }
1337 
1338 // ---------------------------------------------------------------------------
1339 void __fastcall TInterface::SetLengthsButtonClick(TObject *Sender)
1340 {
1341  try
1342  {
1343  TrainController->LogEvent("SetLengthsButtonClick");
1344  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SetLengthsButtonClick");
1345  SelectLengthsFlag = false;
1346  ConstructPrefDir->ExternalClearPrefDirAnd4MultiMap(); // added for extended distances
1348  SetLevel1Mode(55);
1350  SetLevel2TrackMode(19);
1351  Utilities->CallLogPop(1168);
1352  }
1353  catch(const Exception &e)
1354  {
1355  ErrorLog(127, e.Message);
1356  }
1357 }
1358 
1359 // ---------------------------------------------------------------------------
1360 void __fastcall TInterface::LengthOKButtonClick(TObject *Sender)
1361 {
1362  try
1363  {
1364  TrainController->LogEvent("LengthOKButtonClick," + DistanceBox->Text + "," + SpeedLimitBox->Text);
1365  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LengthOKButtonClick");
1366  int Dist = 0, SpeedLimit = 0;
1367  AnsiString DistanceStr = DistanceBox->Text;
1368  if(SelectLengthsFlag && (DistanceStr == ""))
1369  DistanceStr = "No change";
1370  AnsiString SpeedStr = SpeedLimitBox->Text;
1371  if(SelectLengthsFlag && (SpeedStr == ""))
1372  SpeedStr = "No change";
1373  if(SelectLengthsFlag)
1374  {
1375  if(DistanceStr == "No change")
1376  Dist = -1; // i.e.don't change
1377  if(SpeedStr == "No change")
1378  SpeedLimit = -1; // i.e.don't change
1379  }
1380  else
1381  {
1382  if(DistanceStr == AnsiString(OverallDistance))
1383  Dist = -1; // i.e.don't change
1384  if((SpeedStr == "Mixed") || (SpeedStr == AnsiString(OverallSpeedLimit)))
1385  SpeedLimit = -1; // i.e.don't change
1386  }
1387  if(((Dist != -1) && (DistanceStr.Length() > 6)) || ((SpeedLimit != -1) && (SpeedStr.Length() > 6)))
1388  {
1389  ShowMessage("One or more entries too long");
1390  Utilities->CallLogPop(11);
1391  return;
1392  }
1393  if((DistanceStr == "") || (SpeedStr == ""))
1394  {
1395  ShowMessage("One or more entries blank");
1396  Utilities->CallLogPop(12);
1397  return;
1398  }
1399  if(SelectLengthsFlag && (Dist != -1))
1400  {
1401  for(int x = 1; x <= DistanceStr.Length(); x++)
1402  {
1403  if((DistanceStr[x] < '0') || (DistanceStr[x] > '9'))
1404  {
1405  ShowMessage("Track length value must be a positive whole number, or blank for no change");
1406  Utilities->CallLogPop(1415);
1407  return;
1408  }
1409  }
1410  }
1411  if(!SelectLengthsFlag)
1412  {
1413  for(int x = 1; x <= DistanceStr.Length(); x++)
1414  {
1415  if((DistanceStr[x] < '0') || (DistanceStr[x] > '9'))
1416  {
1417  ShowMessage("Distance must be a positive whole number");
1418  Utilities->CallLogPop(13);
1419  return;
1420  }
1421  }
1422  }
1423  if(SelectLengthsFlag && (SpeedLimit != -1))
1424  {
1425  for(int x = 1; x <= SpeedStr.Length(); x++)
1426  {
1427  if((SpeedStr[x] < '0') || (SpeedStr[x] > '9'))
1428  {
1429  ShowMessage("Speed limit must be a positive whole number, or blank for no change");
1430  Utilities->CallLogPop(1416);
1431  return;
1432  }
1433  }
1434  }
1435  if(!SelectLengthsFlag && (SpeedStr != "Mixed"))
1436  {
1437  for(int x = 1; x <= SpeedStr.Length(); x++)
1438  {
1439  if((SpeedStr[x] < '0') || (SpeedStr[x] > '9'))
1440  {
1441  ShowMessage("Speed limit must be a positive whole number, or 'Mixed'");
1442  Utilities->CallLogPop(14);
1443  return;
1444  }
1445  }
1446  }
1447  if(Dist != -1)
1448  Dist = DistanceStr.ToInt();
1449  if(SpeedLimit != -1)
1450  SpeedLimit = SpeedStr.ToInt();
1451 /* don't need this with new condition below
1452  if(SelectLengthsFlag && (Dist != -1) && (Dist < 20))
1453  {
1454  ShowMessage("Track length value must be a minimum of 20m, setting to 20m");
1455  Dist = 20;
1456  }
1457 */
1458  if(((Dist != -1) && (Dist < 20)) || ((SpeedLimit != -1) && (SpeedLimit < 10)) || ((SpeedLimit != -1) && (SpeedLimit > TTrain::MaximumSpeedLimit)))
1459  // new limiting values for v0.6 (used only to fail at either value 0); added TTrain::MaxSpeedLimit at v2.1.0
1460  {
1461  ShowMessage("Lengths must be 20m or more, and speeds must be between 10km/h and 400km/h"); // changed at v2.1.0 to limit max speed
1462  Utilities->CallLogPop(15);
1463  return;
1464  }
1465  DistanceBox->Text = "";
1466  SpeedLimitBox->Text = "";
1467  if(SelectLengthsFlag)
1468  {
1469  int LowSelectHLoc = SelectBitmapHLoc;
1470  int HighSelectHLoc = SelectBitmapHLoc + (SelectBitmap->Width / 16);
1471  int LowSelectVLoc = SelectBitmapVLoc;
1472  int HighSelectVLoc = SelectBitmapVLoc + (SelectBitmap->Height / 16);
1473  bool FoundFlag;
1474  bool NamedLocPresent = false;
1475  if((Dist != -1) && (Dist != DefaultTrackLength))
1476  {
1477  for(int x = LowSelectHLoc; x < HighSelectHLoc; x++)
1478  {
1479  for(int y = LowSelectVLoc; y < HighSelectVLoc; y++)
1480  {
1482  NamedLocPresent = true;
1483  }
1484  }
1485  }
1486  if(NamedLocPresent && (Dist < 50)) // changed in v2.4.0
1487  {
1488  ShowMessage("Note: Named location elements are quite short. If they are too short the simulation might depart too far from reality.");
1489  }
1490 
1491  if(NamedLocPresent && (Dist > 200)) // changed in v2.4.0
1492  {
1493  ShowMessage("Note: Named location elements are quite long. If they are too long the simulation might depart too far from reality.");
1494  }
1495 
1496  for(int x = LowSelectHLoc; x < HighSelectHLoc; x++)
1497  {
1498  for(int y = LowSelectVLoc; y < HighSelectVLoc; y++)
1499  {
1500  int VecPos = Track->GetVectorPositionFromTrackMap(34, x, y, FoundFlag);
1501  if(FoundFlag)
1502  {
1503  if(Dist > -1) // && !(Track->IsPlatformOrNamedNonStationLocationPresent(7, x, y)))
1504  {
1505  Track->TrackElementAt(692, VecPos).Length01 = Dist;
1506  if(Track->TrackElementAt(693, VecPos).Length23 != -1)
1507  {
1508  Track->TrackElementAt(694, VecPos).Length23 = Dist;
1509  }
1510  }
1511  if(SpeedLimit > -1)
1512  {
1513  Track->TrackElementAt(695, VecPos).SpeedLimit01 = SpeedLimit;
1514  if(Track->TrackElementAt(696, VecPos).SpeedLimit23 != -1)
1515  {
1516  Track->TrackElementAt(697, VecPos).SpeedLimit23 = SpeedLimit;
1517  }
1518  }
1519  }
1520  }
1521  }
1522  TrackLengthPanel->Visible = false;
1523  SelectLengthsFlag = false; // go back to normal distance setting mode
1524  }
1525  else
1526  {
1527  SetTrackLengths(1, Dist, SpeedLimit);
1528  }
1530  SetLevel1Mode(57);
1532  SetLevel2TrackMode(21);
1533  Utilities->CallLogPop(16);
1534  }
1535  catch(const Exception &e)
1536  {
1537  ErrorLog(6, e.Message);
1538  }
1539 }
1540 
1541 // ---------------------------------------------------------------------------
1542 void __fastcall TInterface::LengthCancelButtonClick(TObject *Sender)
1543 {
1544  try
1545  {
1546  TrainController->LogEvent("LengthCancelButtonClick");
1547  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LengthCancelButtonClick");
1548  DistanceBox->Text = "";
1549  SpeedLimitBox->Text = "";
1550  TrackLengthPanel->Visible = false;
1551  SelectLengthsFlag = false; // go back to normal distance setting mode
1553  SetLevel1Mode(59);
1555  SetLevel2TrackMode(23);
1556  Utilities->CallLogPop(1169);
1557  }
1558  catch(const Exception &e)
1559  {
1560  ErrorLog(128, e.Message);
1561  }
1562 }
1563 
1564 // ---------------------------------------------------------------------------
1565 void __fastcall TInterface::ResetDefaultLengthButtonClick(TObject *Sender)
1566 {
1567  try
1568  {
1569  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ResetDefaultLengthButtonClick");
1570  TMsgDlgButtons Buttons;
1571  Buttons << mbYes << mbNo;
1572  if(MessageDlg("This will reset the selected elements to default lengths & speed limits. Proceed?", mtWarning, Buttons, 0) == mrNo)
1573  {
1574  // leave all as was before
1575  Utilities->CallLogPop(17);
1576  return;
1577  }
1578  else
1579  {
1580  TrainController->LogEvent("Accepted ResetDefaultLengthButtonClick");
1581  DistanceBox->Text = "";
1582  SpeedLimitBox->Text = "";
1583  if(SelectLengthsFlag)
1584  {
1585  int LowSelectHLoc = SelectBitmapHLoc;
1586  int HighSelectHLoc = SelectBitmapHLoc + (SelectBitmap->Width / 16);
1587  int LowSelectVLoc = SelectBitmapVLoc;
1588  int HighSelectVLoc = SelectBitmapVLoc + (SelectBitmap->Height / 16);
1589  bool FoundFlag;
1590  for(int x = LowSelectHLoc; x < HighSelectHLoc; x++)
1591  {
1592  for(int y = LowSelectVLoc; y < HighSelectVLoc; y++)
1593  {
1594  int VecPos = Track->GetVectorPositionFromTrackMap(35, x, y, FoundFlag);
1595  if(FoundFlag)
1596  {
1598  if(Track->TrackElementAt(699, VecPos).Length23 != -1)
1599  {
1601  }
1603  if(Track->TrackElementAt(702, VecPos).SpeedLimit23 != -1)
1604  {
1606  }
1607  }
1608  }
1609  }
1610  TrackLengthPanel->Visible = false;
1611 // ClearandRebuildRailway(47); don't need this
1612  SelectLengthsFlag = false; // go back to normal distance setting mode
1613  }
1614  else
1615  {
1616  TrackLengthPanel->Visible = false;
1617  bool FoundFlag;
1618  if(ConstructPrefDir->PrefDirSize() == 0)
1619  {
1620  Utilities->CallLogPop(1120);
1621  return;
1622  }
1623  for(unsigned int x = 0; x < ConstructPrefDir->PrefDirSize(); x++)
1624  {
1625  TPrefDirElement PrefDirElement = ConstructPrefDir->GetFixedPrefDirElementAt(169, x);
1626  TTrackElement & TrackElement = Track->TrackElementAt(37, Track->GetVectorPositionFromTrackMap(40, PrefDirElement.HLoc, PrefDirElement.VLoc,
1627  FoundFlag));
1628  if((TrackElement.TrackType == Points) || (TrackElement.TrackType == Crossover) || (TrackElement.TrackType == Bridge))
1629  // only set the relevant track to default length & speed limit
1630  {
1631  if((PrefDirElement.GetELinkPos() < 2) && (PrefDirElement.GetXLinkPos() < 2)) // could be one of each for points
1632  {
1633  TrackElement.Length01 = DefaultTrackLength;
1634  TrackElement.SpeedLimit01 = DefaultTrackSpeedLimit; // 200km/h = 125mph
1635  }
1636  else
1637  {
1638  TrackElement.Length23 = DefaultTrackLength;
1639  TrackElement.SpeedLimit23 = DefaultTrackSpeedLimit; // 200km/h = 125mph
1640  }
1641  }
1642  else // any other 1 track element, including platforms being present
1643  {
1644  if((PrefDirElement.GetELinkPos() > 1) && (PrefDirElement.GetXLinkPos() > 1))
1645  {
1646  throw Exception("Error, XLinkPos > 1 in SetOneDefaultTrackLength at " + AnsiString(TrackElement.HLoc) + " & " +
1647  AnsiString(TrackElement.VLoc));
1648  }
1649  TrackElement.Length01 = DefaultTrackLength;
1650  TrackElement.SpeedLimit01 = DefaultTrackSpeedLimit; // 200km/h = 125mph
1651  TrackElement.Length23 = -1;
1652  TrackElement.SpeedLimit23 = -1;
1653  }
1654  }
1655  }
1657  SetLevel1Mode(61);
1659  SetLevel2TrackMode(25);
1660  }
1661  Utilities->CallLogPop(18);
1662  }
1663  catch(const Exception &e)
1664  {
1665  ErrorLog(7, e.Message);
1666  }
1667 }
1668 
1669 // ---------------------------------------------------------------------------
1670 void __fastcall TInterface::RestoreAllDefaultLengthsButtonClick(TObject *Sender)
1671 {
1672  try
1673  {
1674  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RestoreAllDefaultLengthsButtonClick");
1675  TMsgDlgButtons Buttons;
1676  Buttons << mbYes << mbNo;
1677  if(MessageDlg("This will reset ALL track elements to default lengths & speed limits. Proceed?", mtWarning, Buttons, 0) == mrNo)
1678  {
1679  // leave all as was before
1680  Utilities->CallLogPop(19);
1681  return;
1682  }
1683  else
1684  {
1686  }
1687  TrainController->LogEvent("Accepted RestoreAllDefaultLengthsButtonClick");
1688  DistanceBox->Text = "";
1689  SpeedLimitBox->Text = "";
1690  TrackLengthPanel->Visible = false;
1691  SelectLengthsFlag = false; // go back to normal distance setting mode
1693  SetLevel1Mode(63);
1695  SetLevel2TrackMode(27);
1696  Utilities->CallLogPop(20);
1697  }
1698  catch(const Exception &e)
1699  {
1700  ErrorLog(8, e.Message);
1701  }
1702 }
1703 
1704 // ---------------------------------------------------------------------------
1705 void __fastcall TInterface::ExitTrackButtonClick(TObject *Sender)
1706 {
1707  try
1708  {
1709  TrainController->LogEvent("ExitTrackButtonClick");
1710  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExitTrackButtonClick");
1711  if(Level2TrackMode == CutMoving)
1712  {
1713  Level2TrackMode = Pasting; // to paste the selection
1714  SetLevel2TrackMode(53);
1715  }
1716  DevelopmentPanel->Visible = false; // development use only
1717  ScreenGridFlag = false;
1718  SelectionValid = false;
1719  Track->SelectGraphicVector.clear();
1720  // delete all unwanted TPictures in UserGraphicMap
1721  if(!Track->UserGraphicMap.empty()) // if empty skip it
1722  {
1723  TTrack::TUserGraphicMap::iterator UGMIt = Track->UserGraphicMap.begin();
1724  do
1725  {
1726  bool GraphicFoundInVector = false;
1727  for(TTrack::TUserGraphicVector::iterator UGVIt = Track->UserGraphicVector.begin(); UGVIt < Track->UserGraphicVector.end(); UGVIt++)
1728  {
1729  if(UGMIt->first == UGVIt->FileName)
1730  {
1731  GraphicFoundInVector = true;
1732  break;
1733  }
1734  }
1735  if(!GraphicFoundInVector)
1736  {
1737  delete UGMIt->second;
1738  Track->UserGraphicMap.erase(UGMIt);
1739  UGMIt = Track->UserGraphicMap.begin(); // reset the iterator because erasing an element it points to invalidates it & if use it after then
1740  // behaviour is undefined, the iteration will end eventually because the map has got shorter after an erase
1741  }
1742  else
1743  {
1744  UGMIt++;
1745  }
1746  }
1747  while(UGMIt != Track->UserGraphicMap.end());
1748  }
1749  Level1Mode = BaseMode;
1750  SetLevel1Mode(2);
1751  Utilities->CallLogPop(1170);
1752  }
1753  catch(const Exception &e)
1754  {
1755  ErrorLog(129, e.Message);
1756  }
1757 }
1758 
1759 // ---------------------------------------------------------------------------
1760 void __fastcall TInterface::TextOrUserGraphicGridButtonClick(TObject *Sender)
1761 {
1762  try
1763  {
1764  TrainController->LogEvent("TextOrUserGraphicGridButtonClick," + AnsiString(TextOrUserGraphicGridVal));
1765  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TextOrUserGraphicGridButtonClick");
1766  if(TextOrUserGraphicGridVal == 1)
1767  {
1769  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision2");
1770  }
1771  else if(TextOrUserGraphicGridVal == 2)
1772  {
1774  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision4");
1775  }
1776  else if(TextOrUserGraphicGridVal == 4)
1777  {
1779  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision8");
1780  }
1781  else if(TextOrUserGraphicGridVal == 8)
1782  {
1784  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision16");
1785  }
1786  else
1787  {
1789  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision1");
1790  }
1791  Utilities->CallLogPop(1171);
1792  }
1793  catch(const Exception &e)
1794  {
1795  ErrorLog(130, e.Message);
1796  }
1797 }
1798 
1799 // ---------------------------------------------------------------------------
1800 void __fastcall TInterface::SigAspectButtonClick(TObject *Sender)
1801 {
1802  try
1803  {
1804  TrainController->LogEvent("SigAspectButtonClick," + AnsiString(Track->SignalAspectBuildMode));
1805  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SigAspectButtonClick");
1807  {
1809  SigAspectButton->Glyph->LoadFromResourceName(0, "ThreeAspect");
1810  }
1812  {
1814  SigAspectButton->Glyph->LoadFromResourceName(0, "TwoAspect");
1815  }
1817  {
1819  SigAspectButton->Glyph->LoadFromResourceName(0, "GroundSig");
1820 // set all signal glyphs to ground signals
1822  }
1823  else
1824  {
1826  SigAspectButton->Glyph->LoadFromResourceName(0, "FourAspect");
1827 // set all signal glyphs to normal signals
1829  }
1830  Utilities->CallLogPop(1869);
1831  }
1832  catch(const Exception &e)
1833  {
1834  ErrorLog(180, e.Message);
1835  }
1836 }
1837 
1838 // ---------------------------------------------------------------------------
1839 void __fastcall TInterface::FontButtonClick(TObject *Sender)
1840 {
1841  try
1842  {
1843  TrainController->LogEvent("FontButtonClick");
1844  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",FontButtonClick");
1845  FontDialog->Font = Display->GetFont(); //sets the dialog box font to the currently used font
1846  FontDialog->Execute(); //this displays the dialog box
1847  if(FontDialog->Font->Color == clB5G5R5) //white
1848  FontDialog->Font->Color = clB0G0R0; //black - don't store white in font, will display black as white on dark backgrounds
1849  Display->SetFont(FontDialog->Font); //sets the displayed font to the output from the dialog box
1850  if(TextBox->Visible)
1851  TextBox->SetFocus();
1852  else if(LocationNameTextBox->Visible)
1853  LocationNameTextBox->SetFocus();
1854  Utilities->CallLogPop(1172);
1855  }
1856  catch(const Exception &e)
1857  {
1858  ErrorLog(131, e.Message);
1859  }
1860 }
1861 
1862 // ---------------------------------------------------------------------------
1863 
1864 void __fastcall TInterface::ScreenGridButtonClick(TObject *Sender)
1865 {
1866  try
1867  {
1868  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ScreenGridButtonClick");
1869  if(ScreenGridFlag)
1870  {
1871  TrainController->LogEvent("ScreenGridButtonClick + ScreenGrid off");
1872  ScreenGridFlag = false;
1873  }
1874  else
1875  {
1876  TrainController->LogEvent("ScreenGridButtonClick + ScreenGrid on");
1877  ScreenGridFlag = true;
1878  }
1880  Utilities->CallLogPop(89);
1881  }
1882  catch(const Exception &e)
1883  {
1884  ErrorLog(33, e.Message);
1885  }
1886 }
1887 
1888 // ---------------------------------------------------------------------------
1889 // PrefDir Interface
1890 // ---------------------------------------------------------------------------
1891 void __fastcall TInterface::PlanPrefDirsMenuItemClick(TObject *Sender) // Mode Menu Item
1892 {
1893  try
1894  {
1895  TrainController->LogEvent("PlanPrefDirsMenuItemClick");
1896  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PlanPrefDirsMenuItemClick");
1898  SetLevel1Mode(3);
1899  Utilities->CallLogPop(1173);
1900  }
1901  catch(const Exception &e)
1902  {
1903  ErrorLog(132, e.Message);
1904  }
1905 }
1906 
1907 // ---------------------------------------------------------------------------
1908 void __fastcall TInterface::AddPrefDirButtonClick(TObject *Sender)
1909 {
1910  try
1911  {
1912  TrainController->LogEvent("AddPrefDirButtonClick");
1913  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AddPrefDirButtonClick");
1914  if(ConstructPrefDir->PrefDirSize() == 0)
1915  {
1916  ShowMessage("No preferred direction selection");
1917  Utilities->CallLogPop(22);
1918  return;
1919  }
1920  Screen->Cursor = TCursor(-11); // Hourglass;
1924  SetLevel1Mode(4);
1925  Screen->Cursor = TCursor(-2); // Arrow
1926  Utilities->CallLogPop(23);
1927  }
1928  catch(const Exception &e)
1929  {
1930  ErrorLog(10, e.Message);
1931  }
1932 }
1933 
1934 // ---------------------------------------------------------------------------
1935 void __fastcall TInterface::DeleteAllPrefDirButtonClick(TObject *Sender)
1936 {
1937  try
1938  {
1939  TrainController->LogEvent("DeleteAllPrefDirButtonClick");
1940  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",DeleteAllPrefDirButtonClick");
1941  TMsgDlgButtons Buttons;
1942  Buttons << mbYes << mbNo;
1943  if(MessageDlg("Do you really want to clear all preferred directions?", mtWarning, Buttons, 0) == mrNo)
1944  {
1945  Utilities->CallLogPop(24);
1946  return;
1947  }
1948  // leave all as was before pressed DeleteAllPrefDirButton
1949  else
1950  {
1955  SetLevel1Mode(5);
1956  }
1957  Utilities->CallLogPop(25);
1958  }
1959  catch(const Exception &e)
1960  {
1961  ErrorLog(11, e.Message);
1962  }
1963 }
1964 // ---------------------------------------------------------------------------
1965 
1966 void __fastcall TInterface::DeleteOnePrefDirButtonClick(TObject *Sender)
1967 {
1968  try
1969  {
1970  TrainController->LogEvent("DeleteOnePrefDirButtonClick");
1971  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",DeleteOnePrefDirButtonClick");
1972  ResetChangedFileDataAndCaption(18, false);
1973 // RlyFile = false; - don't alter this just for PrefDir changes
1974  Screen->Cursor = TCursor(-11); // Hourglass;
1975  for(unsigned int x = 0; x < ConstructPrefDir->PrefDirSize(); x++)
1976  {
1979  }
1982  SetLevel1Mode(81); // all PrefDir truncated
1983  Screen->Cursor = TCursor(-2); // Arrow
1984  Utilities->CallLogPop(1591);
1985  }
1986  catch(const Exception &e)
1987  {
1988  ErrorLog(46, e.Message);
1989  }
1990 }
1991 
1992 // ---------------------------------------------------------------------------
1993 
1994 void __fastcall TInterface::ExitPrefDirButtonClick(TObject *Sender)
1995 {
1996  try
1997  {
1998  TrainController->LogEvent("ExitPrefDirButtonClick");
1999  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExitPrefDirButtonClick");
2000  Level1Mode = BaseMode;
2001  SetLevel1Mode(6);
2002  Utilities->CallLogPop(1554);
2003  }
2004  catch(const Exception &e)
2005  {
2006  ErrorLog(133, e.Message);
2007  }
2008 }
2009 
2010 // ---------------------------------------------------------------------------
2011 // Operate Railway Interface
2012 // ---------------------------------------------------------------------------
2013 void __fastcall TInterface::OperateRailwayMenuItemClick(TObject *Sender) // Mode Menu Item
2014 {
2015  try
2016  {
2017  TrainController->LogEvent("OperateRailwayMenuItemClick");
2018  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OperateRailwayMenuItemClick");
2019  TTrain::NextTrainID = 0; // reset to 0 whenever enter operating mode
2020  AllRoutes->NextRouteID = 0; // reset to 0 whenever enter operating mode
2021  Level1Mode = OperMode;
2022  SetLevel1Mode(7);
2023  Utilities->CallLogPop(26);
2024  }
2025  catch(const Exception &e)
2026  {
2027  ErrorLog(12, e.Message);
2028  }
2029 }
2030 
2031 // ---------------------------------------------------------------------------
2032 void __fastcall TInterface::OperateButtonClick(TObject *Sender)
2033 {
2034  try
2035  {
2036  TrainController->LogEvent("StartOperationButtonClick");
2037  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OperateButtonClick");
2039  {
2041  SetLevel2OperMode(0);
2042  }
2043  else
2044  {
2046  SetLevel2OperMode(1);
2047  }
2048  Utilities->CallLogPop(1175);
2049  }
2050  catch(const Exception &e)
2051  {
2052  ErrorLog(37, e.Message);
2053  }
2054 }
2055 
2056 // ---------------------------------------------------------------------------
2057 void __fastcall TInterface::AutoSigsButtonClick(TObject *Sender)
2058  // must have PrefDirs to be available
2059 {
2060  try
2061  {
2062  TrainController->LogEvent("AutoSigsButtonClick");
2063  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AutoSigsButtonClick");
2064  AutoSigsFlag = true;
2065  PreferredRoute = true;
2066  ConsecSignalsRoute = true;
2067 
2068  AutoSigsButton->Enabled = false;
2069  SigPrefButton->Enabled = true;
2070  UnrestrictedButton->Enabled = true;
2071 
2072  InfoPanel->Visible = true;
2073  if(Level2OperMode == PreStart)
2074  InfoPanel->Caption = "PRE-START: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
2075  else
2076  InfoPanel->Caption = "OPERATING: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
2077  InfoCaptionStore = InfoPanel->Caption;
2078  AutoRouteStartMarker->PlotOriginal(1, Display); // if overlay not plotted will ignore
2079  SigRouteStartMarker->PlotOriginal(2, Display); // if overlay not plotted will ignore
2080  NonSigRouteStartMarker->PlotOriginal(3, Display); // if overlay not plotted will ignore
2082  Utilities->CallLogPop(28);
2083  }
2084  catch(const Exception &e)
2085  {
2086  ErrorLog(14, e.Message);
2087  }
2088 }
2089 
2090 // ---------------------------------------------------------------------------
2091 void __fastcall TInterface::SigPrefButtonClick(TObject *Sender)
2092  // must have PrefDirs to be available
2093 {
2094  try
2095  {
2096  TrainController->LogEvent("SigPrefButtonClick");
2097  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SigPrefButtonClick");
2098  AutoSigsFlag = false;
2099  PreferredRoute = true;
2100  ConsecSignalsRoute = true;
2101 
2102  AutoSigsButton->Enabled = true;
2103  SigPrefButton->Enabled = false;
2104  UnrestrictedButton->Enabled = true;
2105 
2106  InfoPanel->Visible = true;
2107  if(Level2OperMode == PreStart)
2108  InfoPanel->Caption = "PRE-START: Select PREFERRED ROUTE start signal, or left click points to change manually";
2109  else
2110  InfoPanel->Caption = "OPERATING: Select PREFERRED ROUTE start signal, or left click points to change manually";
2111  InfoCaptionStore = InfoPanel->Caption;
2112  AutoRouteStartMarker->PlotOriginal(4, Display); // if overlay not plotted will ignore
2113  SigRouteStartMarker->PlotOriginal(5, Display); // if overlay not plotted will ignore
2114  NonSigRouteStartMarker->PlotOriginal(6, Display); // if overlay not plotted will ignore
2116  Utilities->CallLogPop(29);
2117  }
2118  catch(const Exception &e)
2119  {
2120  ErrorLog(15, e.Message);
2121  }
2122 }
2123 
2124 // ---------------------------------------------------------------------------
2125 void __fastcall TInterface::UnrestrictedButtonClick(TObject *Sender)
2126 {
2127  try
2128  {
2129  TrainController->LogEvent("NoSigNonPrefButtonClick");
2130  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",NoSigNonPrefButtonClick");
2131  AutoSigsFlag = false;
2132  PreferredRoute = false;
2133  ConsecSignalsRoute = false;
2134  if(EveryPrefDir->PrefDirSize() > 0)
2135  {
2136  AutoSigsButton->Enabled = true;
2137  SigPrefButton->Enabled = true;
2138  UnrestrictedButton->Enabled = false;
2139  }
2140  else
2141  {
2142  AutoSigsButton->Enabled = false;
2143  SigPrefButton->Enabled = false;
2144  UnrestrictedButton->Enabled = false;
2145  }
2146  InfoPanel->Visible = true;
2147  if(Level2OperMode == PreStart)
2148  InfoPanel->Caption = "PRE-START: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
2149  else
2150  InfoPanel->Caption = "OPERATING: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
2151  InfoCaptionStore = InfoPanel->Caption;
2152  AutoRouteStartMarker->PlotOriginal(7, Display); // if overlay not plotted will ignore
2153  SigRouteStartMarker->PlotOriginal(8, Display); // if overlay not plotted will ignore
2154  NonSigRouteStartMarker->PlotOriginal(9, Display); // if overlay not plotted will ignore
2156  Utilities->CallLogPop(30);
2157  }
2158  catch(const Exception &e)
2159  {
2160  ErrorLog(16, e.Message);
2161  }
2162 }
2163 
2164 // ---------------------------------------------------------------------------
2165 void __fastcall TInterface::RouteCancelButtonClick(TObject *Sender)
2166 {
2167  try
2168  {
2169  TrainController->LogEvent("RouteCancelButtonClick");
2170  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RouteCancelButtonClick");
2171  RouteCancelFlag = true;
2172  InfoPanel->Visible = true;
2173  InfoPanel->Caption = "ROUTE CANCELLING: Right click on truncate element, first element to cancel (anywhere else to skip)";
2174  RouteCancelButton->Enabled = false;
2175  AutoRouteStartMarker->PlotOriginal(32, Display); // if overlay not plotted will ignore
2176  SigRouteStartMarker->PlotOriginal(33, Display); // if overlay not plotted will ignore
2177  NonSigRouteStartMarker->PlotOriginal(34, Display); // if overlay not plotted will ignore
2178  Utilities->CallLogPop(1176);
2179  }
2180  catch(const Exception &e)
2181  {
2182  ErrorLog(35, e.Message);
2183  }
2184 }
2185 
2186 // ---------------------------------------------------------------------------
2187 void __fastcall TInterface::PerformanceLogButtonClick(TObject *Sender)
2188 {
2189  try
2190  {
2191  TrainController->LogEvent("PerformanceLogButtonClick");
2192  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PerformanceLogButtonClick");
2194  {
2195  ShowPerformancePanel = true;
2196  PerformancePanel->Visible = true;
2197  PerformanceLogButton->Glyph->LoadFromResourceName(0, "HideLog");
2198  }
2199  else
2200  {
2201  ShowPerformancePanel = false;
2202  PerformancePanel->Visible = false;
2203  PerformanceLogButton->Glyph->LoadFromResourceName(0, "ShowLog");
2204  }
2205  Utilities->CallLogPop(1177);
2206  }
2207  catch(const Exception &e)
2208  {
2209  ErrorLog(36, e.Message);
2210  }
2211 }
2212 // ---------------------------------------------------------------------------
2213 
2214 void __fastcall TInterface::ExitOperationButtonClick(TObject *Sender)
2215 {
2216  try
2217  {
2218  TrainController->LogEvent("ExitOperationButtonClick");
2219  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExitOperationButtonClick");
2221  {
2222  UnicodeString MessageStr = "Please note that the session will be lost if it hasn't been saved. Do you still wish to exit?";
2223  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
2225  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
2226  TrainController->BaseTime = TDateTime::CurrentDateTime();
2228  if(button == IDNO)
2229  {
2230  Utilities->CallLogPop(751);
2231  return;
2232  }
2233  }
2234  Track->ResetSignals(1);
2235  Track->ResetPoints(1);
2236  TrainController->SendPerformanceSummary(0, Utilities->PerformanceFile); // must come before trains finished becuase examines the train vectors
2237  Utilities->PerformanceFile.close();
2240  RouteMode = None;
2241  PreferredRoute = true;
2242  ConsecSignalsRoute = true;
2244  ShowPerformancePanel = false;
2245  PerformanceLogButton->Glyph->LoadFromResourceName(0, "ShowLog");
2246  ShowOperatorActionPanel = false; // new at v2.2.0
2247  OperatorActionButton->Glyph->LoadFromResourceName(0, "ShowOpActionPanel"); // new v2.2.0
2248  PerformanceLogBox->Lines->Clear();
2249  PerformancePanel->Visible = false;
2250  PerformancePanel->Top = MainScreen->Top + MainScreen->Height - PerformancePanel->Height;
2251  PerformancePanel->Left = MainScreen->Left;
2252 // TipButton->Glyph->LoadFromResourceName(0, "ShowLog"); //'Trains in play' new at v2.2.0
2253  OAListBox->Clear();
2254  OperatorActionPanel->Visible = false;
2255  OperatorActionPanel->Top = MainScreen->Top + MainScreen->Height - OperatorActionPanel->Height;
2256  OperatorActionPanel->Left = MainScreen->Left + MainScreen->Width - OperatorActionPanel->Width; ;
2258  AllRoutes->LockedRouteVector.clear();
2259  Level1Mode = BaseMode;
2260  SetLevel1Mode(8); // calls Clearand...
2261  Utilities->CallLogPop(1555);
2262  }
2263  catch(const Exception &e)
2264  {
2265  ErrorLog(13, e.Message);
2266  }
2267 }
2268 
2269 // ---------------------------------------------------------------------------
2270 // Menu Interface (for items not already covered above)
2271 // ---------------------------------------------------------------------------
2272 void __fastcall TInterface::LoadRailwayMenuItemClick(TObject *Sender)
2273 {
2274  try
2275  {
2276  TrainController->LogEvent("LoadRailwayMenuItemClick");
2277  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LoadRailwayMenuItemClick");
2278  if(!ClearEverything(1))
2279  {
2280  Utilities->CallLogPop(1139);
2281  return;
2282  }
2283  // LoadRailwayDialog->Filter = "Development file (*.dev)|*.dev|Railway file (*.rly)|*.rly"; //as was
2284  // changed at v2.0.0 (Embarcadero change) to show all files together
2285  LoadRailwayDialog->Filter = "Railway files (*.rly or *.dev)|*.rly; *.dev";
2286  if(LoadRailwayDialog->Execute())
2287  {
2288  if(LoadRailwayDialog->InitialDir != TPath::GetDirectoryName(LoadRailwayDialog->FileName))//new at v2.6.0 to retain a new directory
2289  {
2290  LoadRailwayDialog->InitialDir = TPath::GetDirectoryName(LoadRailwayDialog->FileName);
2291  SaveRailwayDialog->InitialDir = TPath::GetDirectoryName(LoadRailwayDialog->FileName);
2292  }
2293  TrainController->LogEvent("LoadRailway " + AnsiString(LoadRailwayDialog->FileName));
2294  LoadRailway(0, AnsiString(LoadRailwayDialog->FileName));
2295  }
2296  // else ShowMessage("Load Aborted"); drop this
2297  // Display->Update(); //display updated in ClearandRebuildRailway
2298  Track->CalcHLocMinEtc(9);
2299  Level1Mode = BaseMode;
2302  SetLevel1Mode(11); // calls Clearand... to plot the new railway
2303  Utilities->CallLogPop(31);
2304  }
2305  catch(const Exception &e)
2306  {
2307  ErrorLog(17, e.Message);
2308  }
2309 }
2310 // ---------------------------------------------------------------------------
2311 
2312 void TInterface::LoadRailway(int Caller, AnsiString LoadFileName)
2313 { // display of the loaded railway covered in the calling routine
2314  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadRailway," + LoadFileName);
2315  if(FileIntegrityCheck(0, LoadFileName.c_str()))
2316  {
2317  Screen->Cursor = TCursor(-11); // Hourglass;
2318  std::ifstream VecFile(LoadFileName.c_str());
2319  if(!(VecFile.fail()))
2320  {
2321  AnsiString TempString = Utilities->LoadFileString(VecFile); // version number
2322  int TempOffsetHHome = Utilities->LoadFileInt(VecFile);
2323  int TempOffsetVHome = Utilities->LoadFileInt(VecFile);
2324  bool GraphicsFollow = false;
2325  // can't load DisplayOffsetH & VHome until after LoadTrack as that calls TrackClear & zeroes them
2326 // load track elements
2327  Track->LoadTrack(1, VecFile, GraphicsFollow);
2328 // load text elements
2329  TextHandler->LoadText(0, VecFile);
2330 // load PrefDir elements
2331  EveryPrefDir->LoadPrefDir(0, VecFile);
2332  if(GraphicsFollow)
2333  {
2334 // load user graphics
2335  Track->LoadGraphics(0, VecFile, CurDir + "\\" + USERGRAPHICS_DIR_NAME); // include path to Graphics folder
2336  }
2337  EveryPrefDir->CheckPrefDirAgainstTrackVector(0); // clears PrefDir if any discrepancies found
2338  VecFile.close();
2339  Display->DisplayOffsetHHome = TempOffsetHHome;
2340  Display->DisplayOffsetVHome = TempOffsetVHome;
2342 
2343  TFont *TempFont = new TFont; // if try to alter MainScreen->Canvas->Font directly it won't change the style for some reason
2344  TempFont->Style.Clear();
2345  TempFont->Name = "MS Sans Serif"; // reset font, else stays set to last displayed text font
2346  TempFont->Size = 10;
2347  TempFont->Color = clB0G0R0;
2348  TempFont->Charset = (TFontCharset)(0);
2349  MainScreen->Canvas->Font->Assign(TempFont);
2350  delete TempFont;
2351 
2352 // calculate starting zoomed out offset values - same as when zoom out button clicked
2353  int OVOffH_NVCentre = Display->DisplayOffsetH - (1.5 * Utilities->ScreenElementWidth);
2354 // start zoomout centre at DisplayOffsetH + 30 - zoomout width/2 = -(1.5 * 60)
2355  int LeftExcess = OVOffH_NVCentre - Track->GetHLocMin();
2356  int RightExcess = Track->GetHLocMax() - OVOffH_NVCentre - ((4 * Utilities->ScreenElementWidth) - 1);
2357  if((LeftExcess > 0) && (RightExcess > 0))
2358  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre;
2359  else if((LeftExcess > 0) && (RightExcess <= 0))
2360  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre + ((RightExcess) / (Utilities->ScreenElementWidth / 2)) *
2361  (Utilities->ScreenElementWidth / 2); // normalise to nearest half screen
2362  else if((LeftExcess <= 0) && (RightExcess > 0))
2363  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre - ((LeftExcess) / (Utilities->ScreenElementWidth / 2)) * (Utilities->ScreenElementWidth / 2);
2364  else
2365  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre; // no excess at either side, so display in centre
2366 
2367  int OVOffV_NVCentre = Display->DisplayOffsetV - (1.5 * Utilities->ScreenElementHeight);
2368  int TopExcess = OVOffV_NVCentre - Track->GetVLocMin();
2369  int BotExcess = Track->GetVLocMax() - OVOffV_NVCentre - ((4 * Utilities->ScreenElementHeight) - 1);
2370  if((TopExcess > 0) && (BotExcess > 0))
2371  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre;
2372  else if((TopExcess > 0) && (BotExcess <= 0))
2373  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre + ((BotExcess) / (Utilities->ScreenElementHeight / 2)) *
2374  (Utilities->ScreenElementHeight / 2); // normalise to nearest half screen
2375  else if((TopExcess <= 0) && (BotExcess > 0))
2376  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre - ((TopExcess) / (Utilities->ScreenElementHeight / 2)) * (Utilities->ScreenElementHeight / 2);
2377  else
2378  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre; // no excess at either side, so display in centre
2379 // all above same as when zoom out button clicked
2380  Display->DisplayZoomOutOffsetVHome = Display->DisplayZoomOutOffsetV; // now set zoomed out 'home' values
2382 
2383  SavedFileName = AnsiString(LoadRailwayDialog->FileName); // includes the full PrefDir
2384  if(SavedFileName != "") // shouldn't be "" at this stage but leave in as a safeguard
2385  {
2386  Track->DuplicatedLocationName(1, true);
2387  char LastChar = SavedFileName[SavedFileName.Length()];
2388  if((LastChar == 'y') || (LastChar == 'Y'))
2389  {
2390  if(!(Track->IsReadyForOperation(false)))
2391  {
2392  ShowMessage("Railway not ready for operation so unable to load as a .rly file. Loading as a new railway under development");
2393  SavedFileName = "";
2394  RlyFile = false;
2395  RailwayTitle = "";
2396  TimetableTitle = "";
2397  SetCaption(5);
2398  Track->CalcHLocMinEtc(1);
2399  Screen->Cursor = TCursor(-2); // Arrow
2400  Level1Mode = BaseMode;
2401  SetLevel1Mode(9);
2402  Utilities->CallLogPop(1136);
2403  return;
2404  }
2405  else
2406  {
2407  RlyFile = true;
2408  }
2409  }
2410  else
2411  {
2412  RlyFile = false;
2413  }
2414  }
2415  else
2416  {
2417  RlyFile = false;
2418  }
2419  FileChangedFlag = false;
2420  for(int x = AnsiString(LoadRailwayDialog->FileName).Length(); x > 0; x--)
2421  {
2422  if(AnsiString(LoadRailwayDialog->FileName)[x] == '\\')
2423  {
2424  RailwayTitle = AnsiString(LoadRailwayDialog->FileName).SubString(x + 1, AnsiString(LoadRailwayDialog->FileName).Length() - x - 4);
2425  TimetableTitle = "";
2426  SetCaption(6);
2427  break;
2428  }
2429  }
2430  } // if(VecFile)
2431  else
2432  ShowMessage("File open failed prior to load");
2433  Screen->Cursor = TCursor(-2); // Arrow
2434  } // if(FileIntegrityCheck(LoadRailwayDialog->FileName.c_str()))
2435  else
2436  ShowMessage("File integrity check failed - unable to load");
2437  Utilities->CallLogPop(1774);
2438 }
2439 
2440 // ---------------------------------------------------------------------------
2441 
2442 void __fastcall TInterface::SaveMenuItemClick(TObject *Sender)
2443 {
2444 // save under existing name
2445 // no need to alter RlyFile for saving under existing name
2446 
2447  try
2448  {
2449  TrainController->LogEvent("SaveMenuItemClick, " + SavedFileName);
2450  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveMenuItemClick");
2451  Screen->Cursor = TCursor(-11); // Hourglass;
2452  std::ofstream VecFile(SavedFileName.c_str());
2453  if(!(VecFile.fail()))
2454  {
2458  // save track elements
2459  if(Track->UserGraphicVector.empty())
2460  {
2461  Track->SaveTrack(3, VecFile, false); // false for no graphics (**Active elements** saved as marker)
2462  }
2463  else
2464  {
2465  Track->SaveTrack(8, VecFile, true); // true for graphics to be saved (**Active elements**1 saved as marker)
2466  }
2467  // save text elements
2468  TextHandler->SaveText(0, VecFile);
2469  // save PrefDir elements
2470  EveryPrefDir->SavePrefDirVector(0, VecFile);
2471  if(!Track->UserGraphicVector.empty())
2472  {
2473  // save user graphics
2474  Track->SaveUserGraphics(0, VecFile);
2475  }
2476  FileChangedFlag = false;
2477  VecFile.close();
2478  }
2479  else
2480  ShowMessage("File open failed prior to save");
2481  Screen->Cursor = TCursor(-2); // Arrow
2482  Level1Mode = BaseMode;
2483  SetLevel1Mode(12); // to disable the save option
2484  Utilities->CallLogPop(1178);
2485  }
2486  catch(const Exception &e)
2487  {
2488  ErrorLog(135, e.Message);
2489  }
2490 }
2491 
2492 // ---------------------------------------------------------------------------
2493 void __fastcall TInterface::SaveAsMenuItemClick(TObject *Sender)
2494 {
2495  try
2496  {
2497  TrainController->LogEvent("SaveAsMenuItemClick");
2498  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveAsMenuItemClick");
2499  SaveAsSubroutine(0);
2500  Utilities->CallLogPop(32);
2501  }
2502  catch(const Exception &e)
2503  {
2504  ErrorLog(18, e.Message);
2505  }
2506 }
2507 
2508 // ---------------------------------------------------------------------------
2509 
2510 void __fastcall TInterface::SaveImageNoGridMenuItemClick(TObject *Sender)
2511 { // need to stop clock in case invoke during operation
2512  try
2513  {
2514  TrainController->LogEvent("SaveImageNoGridMenuItemClick");
2515  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveImageNoGridMenuItemClick");
2516  if(!DirectoryExists(CurDir + "\\" + IMAGE_DIR_NAME))
2517  {
2518  ShowMessage("Failed to find folder " + IMAGE_DIR_NAME + " in the folder where 'railway.exe' resides. Image can't be saved");
2519  Utilities->CallLogPop(1695);
2520  return;
2521  }
2522  Screen->Cursor = TCursor(-11); // Hourglass;
2523  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
2525  AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
2526  // format "16/06/2009 20:55:17"
2527  // avoid characters in filename:= / \ : * ? " < > |
2528  ImageFileName = CurDir + "\\" + IMAGE_DIR_NAME + "\\RailwayImage " + ImageFileName + "; " + RailwayTitle + ".bmp";
2529  AnsiString ShortName = "";
2530  for(int x = ImageFileName.Length(); x > 0; x--)
2531  {
2532  if(ImageFileName[x] == '\\')
2533  {
2534  ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
2535  break;
2536  }
2537  }
2538  ShowMessage("A bitmap file named " + ShortName + " will be created in the Images folder");
2539  Graphics::TBitmap *RailwayImage = new Graphics::TBitmap;
2540  RailwayImage->PixelFormat = pf8bit; // needed to ensure compatibility with track
2541 
2542  int HPosMin = Track->GetHLocMin() * 16;
2543  int HPosMax = (Track->GetHLocMax() + 1) * 16;
2544  int VPosMin = Track->GetVLocMin() * 16;
2545  int VPosMax = (Track->GetVLocMax() + 1) * 16;
2546  RailwayImage->Width = HPosMax - HPosMin;
2547  RailwayImage->Height = VPosMax - VPosMin;
2548 
2549  // need to check if there is any text that extends past HPosMax or below VPosMax
2550  // use font height x text length x .7 for new rh calc & font height * 1.5 for new bottom calc
2551  if(!TextHandler->TextVector.empty())
2552  {
2553  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr != TextHandler->TextVector.end(); TextPtr++)
2554  {
2555  int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
2556  int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
2557  if(NewWidth > RailwayImage->Width)
2558  {
2559  RailwayImage->Width = NewWidth;
2560  }
2561  if(NewHeight > RailwayImage->Height)
2562  {
2563  RailwayImage->Height = NewHeight;
2564  }
2565  }
2566  }
2567 
2568  RailwayImage->Canvas->Brush->Color = clB5G5R5; // set it all to white initially
2569  TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
2570  RailwayImage->Canvas->FillRect(Rect);
2571 
2572  // write graphics first so text & track overwrite
2573  Track->WriteGraphicsToImage(0, RailwayImage);
2574  // then write text so track overwrites
2575  TextHandler->WriteTextToImage(0, RailwayImage);
2576  Track->WriteTrackToImage(0, RailwayImage);
2577 
2578  RailwayImage->SaveToFile(ImageFileName);
2579  delete RailwayImage;
2580  TrainController->BaseTime = TDateTime::CurrentDateTime();
2582  Screen->Cursor = TCursor(-2); // Arrow
2583  Utilities->CallLogPop(1535);
2584  }
2585  catch(const Exception &e)
2586  {
2587  if(e.Message.Pos("torage") > 0) // 'storage', avoid capitals as may be OS dependent
2588  {
2589  Screen->Cursor = TCursor(-2); // Arrow;
2590  UnicodeString MessageStr = "Insufficient memory available to store this image";
2591  Application->MessageBox(MessageStr.c_str(), L"", MB_OK | MB_ICONWARNING);
2592  }
2593  else
2594  {
2595  ErrorLog(42, e.Message);
2596  }
2597  }
2598 }
2599 
2600 // ---------------------------------------------------------------------------
2601 
2602 void __fastcall TInterface::SaveImageAndGridMenuItemClick(TObject *Sender)
2603 { // need to stop clock in case invoke during operation
2604  try
2605  {
2606  TrainController->LogEvent("SaveImageAndGridMenuItemClick");
2607  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveImageAndGridMenuItemClick");
2608  if(!DirectoryExists(CurDir + "\\" + IMAGE_DIR_NAME))
2609  {
2610  ShowMessage("Failed to find folder " + IMAGE_DIR_NAME + " in the folder where 'railway.exe' resides. Image can't be saved");
2611  Utilities->CallLogPop(1696);
2612  return;
2613  }
2614  Screen->Cursor = TCursor(-11); // Hourglass;
2615  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
2617  AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
2618  // format "16/06/2009 20:55:17"
2619  // avoid characters in filename:= / \ : * ? " < > |
2620  ImageFileName = CurDir + "\\" + IMAGE_DIR_NAME + "\\RailwayImage " + ImageFileName + "; " + RailwayTitle + ".bmp";
2621  AnsiString ShortName = "";
2622  for(int x = ImageFileName.Length(); x > 0; x--)
2623  {
2624  if(ImageFileName[x] == '\\')
2625  {
2626  ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
2627  break;
2628  }
2629  }
2630  ShowMessage("A bitmap file named " + ShortName + " will be created in the Images folder");
2631  Graphics::TBitmap *RailwayImage = new Graphics::TBitmap;
2632  RailwayImage->PixelFormat = pf8bit; // needed to ensure compatibility with track
2633  int HPosMin = Track->GetHLocMin() * 16;
2634  int HPosMax = (Track->GetHLocMax() + 1) * 16;
2635  int VPosMin = Track->GetVLocMin() * 16;
2636  int VPosMax = (Track->GetVLocMax() + 1) * 16;
2637  RailwayImage->Width = HPosMax - HPosMin;
2638  RailwayImage->Height = VPosMax - VPosMin;
2639 
2640  // need to check if there is any text that extends past HPosMax or below VPosMax
2641  // use font height x text length x .7 for new rh calc & font height * 1.5 for new bottom calc
2642  if(!TextHandler->TextVector.empty())
2643  {
2644  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr != TextHandler->TextVector.end(); TextPtr++)
2645  {
2646  int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
2647  int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
2648  if(NewWidth > RailwayImage->Width)
2649  {
2650  RailwayImage->Width = NewWidth;
2651  }
2652  if(NewHeight > RailwayImage->Height)
2653  {
2654  RailwayImage->Height = NewHeight;
2655  }
2656  }
2657  }
2658 
2659  RailwayImage->Canvas->Brush->Color = clB5G5R5; // set it all to white initially
2660  TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
2661  RailwayImage->Canvas->FillRect(Rect);
2662 
2663  // write the grid first so all else on top
2664  for(int x = 0; x < ((RailwayImage->Width) / 16); x++)
2665  {
2666  for(int y = 0; y < ((RailwayImage->Height) / 16); y++)
2667  {
2668  RailwayImage->Canvas->Draw((x * 16), (y * 16), RailGraphics->bmGrid); // graphic is black on white so no need to change
2669  }
2670  }
2671  // write graphics next so text & track overwrite
2672  Track->WriteGraphicsToImage(1, RailwayImage);
2673  // then write text so track overwrites
2674  TextHandler->WriteTextToImage(1, RailwayImage);
2675  Track->WriteTrackToImage(1, RailwayImage);
2676  RailwayImage->SaveToFile(ImageFileName);
2677  delete RailwayImage;
2678  TrainController->BaseTime = TDateTime::CurrentDateTime();
2680  Screen->Cursor = TCursor(-2); // Arrow
2681  Utilities->CallLogPop(1536);
2682  }
2683  catch(const Exception &e)
2684  {
2685  if(e.Message.Pos("torage") > 0) // 'storage', avoid capitals as may be OS dependent
2686  {
2687  Screen->Cursor = TCursor(-2); // Arrow;
2688  UnicodeString MessageStr = "Insufficient memory available to store this image";
2689  Application->MessageBox(MessageStr.c_str(), L"", MB_OK | MB_ICONWARNING);
2690  }
2691  else
2692  {
2693  ErrorLog(43, e.Message);
2694  }
2695  }
2696 }
2697 // ---------------------------------------------------------------------------
2698 
2699 void __fastcall TInterface::SaveImageAndPrefDirsMenuItemClick(TObject *Sender)
2700 { // need to stop clock in case invoke during operation
2701  try
2702  {
2703  TrainController->LogEvent("SaveImageAndPrefDirsMenuItemClick");
2704  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveImageAndPrefDirsMenuItemClick");
2705  if(!DirectoryExists(CurDir + "\\" + IMAGE_DIR_NAME))
2706  {
2707  ShowMessage("Failed to find folder " + IMAGE_DIR_NAME + " in the folder where 'railway.exe' resides. Image can't be saved");
2708  Utilities->CallLogPop(1697);
2709  return;
2710  }
2711  Screen->Cursor = TCursor(-11); // Hourglass;
2712  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
2714  AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
2715  // format "16/06/2009 20:55:17"
2716  // avoid characters in filename:= / \ : * ? " < > |
2717  ImageFileName = CurDir + "\\" + IMAGE_DIR_NAME + "\\RailwayImage " + ImageFileName + "; " + RailwayTitle + ".bmp";
2718  AnsiString ShortName = "";
2719  for(int x = ImageFileName.Length(); x > 0; x--)
2720  {
2721  if(ImageFileName[x] == '\\')
2722  {
2723  ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
2724  break;
2725  }
2726  }
2727  ShowMessage("A bitmap file named " + ShortName + " will be created in the Images folder");
2728  Graphics::TBitmap *RailwayImage = new Graphics::TBitmap;
2729  RailwayImage->PixelFormat = pf8bit; // needed to ensure compatibility with track
2730  int HPosMin = Track->GetHLocMin() * 16;
2731  int HPosMax = (Track->GetHLocMax() + 1) * 16;
2732  int VPosMin = Track->GetVLocMin() * 16;
2733  int VPosMax = (Track->GetVLocMax() + 1) * 16;
2734  RailwayImage->Width = HPosMax - HPosMin;
2735  RailwayImage->Height = VPosMax - VPosMin;
2736 
2737  // need to check if there is any text that extends past HPosMax or below VPosMax
2738  // use font height x text length x .7 for new rh calc & font height * 1.5 for new bottom calc
2739  if(!TextHandler->TextVector.empty())
2740  {
2741  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr != TextHandler->TextVector.end(); TextPtr++)
2742  {
2743  int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
2744  int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
2745  if(NewWidth > RailwayImage->Width)
2746  {
2747  RailwayImage->Width = NewWidth;
2748  }
2749  if(NewHeight > RailwayImage->Height)
2750  {
2751  RailwayImage->Height = NewHeight;
2752  }
2753  }
2754  }
2755 
2756  RailwayImage->Canvas->Brush->Color = clB5G5R5; // set it all to white initially
2757  TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
2758  RailwayImage->Canvas->FillRect(Rect);
2759 
2760  // write graphics first so text & track overwrite
2761  Track->WriteGraphicsToImage(2, RailwayImage);
2762  // then write text so track overwrites
2763  TextHandler->WriteTextToImage(2, RailwayImage);
2764  Track->WriteTrackToImage(2, RailwayImage);
2765  EveryPrefDir->WritePrefDirToImage(0, RailwayImage);
2766  RailwayImage->SaveToFile(ImageFileName);
2767  delete RailwayImage;
2768  TrainController->BaseTime = TDateTime::CurrentDateTime();
2770  Screen->Cursor = TCursor(-2); // Arrow
2771  Utilities->CallLogPop(1566);
2772  }
2773  catch(const Exception &e)
2774  {
2775  if(e.Message.Pos("torage") > 0) // 'storage', avoid capitals as may be OS dependent
2776  {
2777  Screen->Cursor = TCursor(-2); // Arrow;
2778  UnicodeString MessageStr = "Insufficient memory available to store this image";
2779  Application->MessageBox(MessageStr.c_str(), L"", MB_OK | MB_ICONWARNING);
2780  }
2781  else
2782  {
2783  ErrorLog(45, e.Message);
2784  }
2785  }
2786 }
2787 // ---------------------------------------------------------------------------
2788 
2789 void __fastcall TInterface::SaveOperatingImageMenuItemClick(TObject *Sender)
2790 { // need to stop clock
2791  try
2792  {
2793  TrainController->LogEvent("SaveOperatingImageMenuItemClick");
2794  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveOperatingImageMenuItemClick");
2795  if(!DirectoryExists(CurDir + "\\" + IMAGE_DIR_NAME))
2796  {
2797  ShowMessage("Failed to find folder " + IMAGE_DIR_NAME + " in the folder where 'railway.exe' resides. Image can't be saved");
2798  Utilities->CallLogPop(1702);
2799  return;
2800  }
2801  Screen->Cursor = TCursor(-11); // Hourglass;
2802  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
2804 
2805  AnsiString TimetableTimeStr = Utilities->Format96HHMMSS(TrainController->TTClockTime);
2806  TimetableTimeStr = TimetableTimeStr.SubString(1, 2) + '.' + TimetableTimeStr.SubString(4, 2) + '.' + TimetableTimeStr.SubString(7, 2);
2807  AnsiString ImageFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
2808  // format "16/06/2009 20:55:17"
2809  // avoid characters in filename:= / \ : * ? " < > |
2810  ImageFileName = CurDir + "\\" + IMAGE_DIR_NAME + "\\RailwayImage " + ImageFileName + "; Timetable time " + TimetableTimeStr + "; " + RailwayTitle +
2811  "; " + TimetableTitle + ".bmp";
2812  AnsiString ShortName = "";
2813  for(int x = ImageFileName.Length(); x > 0; x--)
2814  {
2815  if(ImageFileName[x] == '\\')
2816  {
2817  ShortName = ImageFileName.SubString(x + 1, ImageFileName.Length() - x - 4);
2818  break;
2819  }
2820  }
2821  ShowMessage("A bitmap file named " + ShortName + " will be created in the Images folder");
2822  Graphics::TBitmap *RailwayImage = new Graphics::TBitmap;
2823  RailwayImage->PixelFormat = pf8bit; // needed to ensure compatibility with track
2824  int HPosMin = Track->GetHLocMin() * 16;
2825  int HPosMax = (Track->GetHLocMax() + 1) * 16;
2826  int VPosMin = Track->GetVLocMin() * 16;
2827  int VPosMax = (Track->GetVLocMax() + 1) * 16;
2828  RailwayImage->Width = HPosMax - HPosMin;
2829  RailwayImage->Height = VPosMax - VPosMin;
2830 
2831  // need to check if there is any text that extends past HPosMax or below VPosMax
2832  // use font height x text length x .7 for new rh calc & font height * 1.5 for new bottom calc
2833  if(!TextHandler->TextVector.empty())
2834  {
2835  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr != TextHandler->TextVector.end(); TextPtr++)
2836  {
2837  int NewWidth = (TextPtr->HPos - HPosMin) + (abs(TextPtr->Font->Height) * TextPtr->TextString.Length() * 0.7);
2838  int NewHeight = (TextPtr->VPos - VPosMin) + (abs(TextPtr->Font->Height) * 1.5);
2839  if(NewWidth > RailwayImage->Width)
2840  {
2841  RailwayImage->Width = NewWidth;
2842  }
2843  if(NewHeight > RailwayImage->Height)
2844  {
2845  RailwayImage->Height = NewHeight;
2846  }
2847  }
2848  }
2849 
2850  RailwayImage->Canvas->Brush->Color = clB5G5R5; // set it all to white initially
2851  TRect Rect(0, 0, RailwayImage->Width, RailwayImage->Height);
2852  RailwayImage->Canvas->FillRect(Rect);
2853 
2854  // write graphics first so text & track overwrite
2855  Track->WriteGraphicsToImage(3, RailwayImage);
2856  // then write text so track overwrites
2857  TextHandler->WriteTextToImage(3, RailwayImage);
2858  Track->WriteOperatingTrackToImage(0, RailwayImage); // need points with single fillets, signals with colours, gaps all connected
2859  AllRoutes->WriteAllRoutesToImage(0, RailwayImage);
2860 // add any locked route markers
2861  if(!AllRoutes->LockedRouteVector.empty())
2862  {
2863  for(TAllRoutes::TLockedRouteVectorIterator LRVIT = AllRoutes->LockedRouteVector.end() - 1; LRVIT >= AllRoutes->LockedRouteVector.begin(); LRVIT--)
2864  {
2865  TOneRoute Route = AllRoutes->GetFixedRouteAt(167, LRVIT->RouteNumber);
2866  int x = Route.PrefDirSize() - 1;
2867  bool BreakFlag = false;
2868  TPrefDirElement PrefDirElement = Route.GetFixedPrefDirElementAt(188, x);
2869  while(PrefDirElement.GetTrackVectorPosition() != LRVIT->TruncateTrackVectorPosition)
2870  {
2871  RailwayImage->Canvas->Draw((PrefDirElement.HLoc - Track->GetHLocMin()) * 16, (PrefDirElement.VLoc - Track->GetVLocMin()) * 16,
2872  RailGraphics->LockedRouteCancelPtr[PrefDirElement.GetELink()]);
2873  if(!(AllRoutes->TrackIsInARoute(13, PrefDirElement.Conn[PrefDirElement.GetELinkPos()],
2874  PrefDirElement.ConnLinkPos[PrefDirElement.GetELinkPos()])))
2875  {
2876  BreakFlag = true;
2877  break; // train removed earlier element from route so stop here
2878  }
2879  x--;
2880  PrefDirElement = Route.GetFixedPrefDirElementAt(180, x);
2881  }
2882  if(!BreakFlag)
2883  {
2884  if(PrefDirElement.GetTrackVectorPosition() == LRVIT->TruncateTrackVectorPosition)
2885  {
2886  RailwayImage->Canvas->Draw((PrefDirElement.HLoc - Track->GetHLocMin()) * 16, (PrefDirElement.VLoc - Track->GetVLocMin()) * 16,
2887  RailGraphics->LockedRouteCancelPtr[PrefDirElement.GetELink()]);
2888  }
2889  }
2890  }
2891  }
2892  TrainController->WriteTrainsToImage(0, RailwayImage);
2893  RailwayImage->SaveToFile(ImageFileName);
2894  delete RailwayImage;
2895  TrainController->BaseTime = TDateTime::CurrentDateTime();
2897  Screen->Cursor = TCursor(-2); // Arrow
2898  Utilities->CallLogPop(1703);
2899  }
2900  catch(const Exception &e)
2901  {
2902  if(e.Message.Pos("torage") > 0) // 'storage', avoid capitals as may be OS dependent
2903  {
2904  Screen->Cursor = TCursor(-2); // Arrow;
2905  UnicodeString MessageStr = "Insufficient memory available to store this image";
2906  Application->MessageBox(MessageStr.c_str(), L"", MB_OK | MB_ICONWARNING);
2907  }
2908  else
2909  {
2910  ErrorLog(113, e.Message); //NB: DO NOT CHANGE THIS ERROR NUMBER - THE DISPLAYED MESSAGE DEPENDS ON IT
2911  }
2912  }
2913 }
2914 
2915 // ---------------------------------------------------------------------------
2916 
2917 void __fastcall TInterface::SaveHeaderMenu1Click(TObject *Sender)
2918 {
2919 //
2920  try
2921  {
2922  TrainController->LogEvent("SaveHeaderMenu1Click");
2923  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveHeaderMenu1Click");
2924  if(Sender == SaveSessionButton)
2925  {
2926  SaveSessionFlag = true;
2927  }
2928  else if(SavedFileName == "") // use 'Save As' function
2929  {
2930  SaveAsSubroutine(1);
2931  }
2932  else // ordinary save
2933  {
2934  Screen->Cursor = TCursor(-11); // Hourglass;
2935  std::ofstream VecFile(SavedFileName.c_str());
2936  if(!(VecFile.fail()))
2937  {
2941  // save track elements
2942  if(Track->UserGraphicVector.empty())
2943  {
2944  Track->SaveTrack(9, VecFile, false); // false for no graphics (**Active elements** saved as marker)
2945  }
2946  else
2947  {
2948  Track->SaveTrack(10, VecFile, true); // true for graphics to be saved (**Active elements**1 saved as marker)
2949  }
2950  // save text elements
2951  TextHandler->SaveText(5, VecFile);
2952  // save PrefDir elements
2953  EveryPrefDir->SavePrefDirVector(8, VecFile);
2954  if(!Track->UserGraphicVector.empty())
2955  {
2956  // save user graphics
2957  Track->SaveUserGraphics(1, VecFile);
2958  }
2959  FileChangedFlag = false;
2960  VecFile.close();
2961  }
2962  else
2963  ShowMessage("Railway failed to save - can't open file");
2964  Screen->Cursor = TCursor(-2); // Arrow
2965  }
2966  Utilities->CallLogPop(1552);
2967  }
2968  catch(const Exception &e)
2969  {
2970  ErrorLog(44, e.Message);
2971  }
2972 }
2973 
2974 // ---------------------------------------------------------------------------
2975 void __fastcall TInterface::LoadSessionMenuItemClick(TObject *Sender)
2976 {
2977  try
2978  {
2979  TrainController->LogEvent("LoadSessionMenuItemClick");
2980  LoadSessionFlag = true; // load session within ClockTimer2
2981  }
2982  catch(const Exception &e)
2983  {
2984  ErrorLog(136, e.Message);
2985  }
2986 }
2987 
2988 // ---------------------------------------------------------------------------
2989 void __fastcall TInterface::ClearAllMenuItemClick(TObject *Sender)
2990 {
2991  try
2992  {
2993  TrainController->LogEvent("ClearAllMenuItemClick");
2994  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ClearAllMenuItemClick");
2995  if(ClearEverything(2))
2996  {;
2997  } // no change in action on result
2998  Level1Mode = BaseMode;
2999  SetLevel1Mode(126);
3000  Utilities->CallLogPop(1179);
3001  }
3002  catch(const Exception &e)
3003  {
3004  ErrorLog(137, e.Message);
3005  }
3006 }
3007 
3008 // ---------------------------------------------------------------------------
3009 void __fastcall TInterface::ExportTTMenuItemClick(TObject *Sender)
3010 { // no need to stop clock as can't be called when railway operating
3011  try
3012  {
3013  TrainController->LogEvent("ExportTTMenuItemClick");
3014  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExportTTMenuItemClick");
3015  if(!DirectoryExists(CurDir + "\\" + FORMATTEDTT_DIR_NAME))
3016  {
3017  ShowMessage("Failed to find folder " + FORMATTEDTT_DIR_NAME + " in the folder where 'railway.exe' resides. Timetable can't be exported");
3018  Utilities->CallLogPop(1699);
3019  return;
3020  }
3021 // Screen->Cursor = TCursor(-11); // Hourglass; - no good setting here as it's reset by ShowMessage in CreateFormattedTimetable. It's set there after
3022 // the message instead, but reset here afterwards
3023  // no need to stop clock as can't select this if operating
3025  Screen->Cursor = TCursor(-2); // Arrow - reset after above function returns
3026  Utilities->CallLogPop(1573);
3027  }
3028  catch(const Exception &e)
3029  {
3030  ErrorLog(138, e.Message);
3031  }
3032 }
3033 // ---------------------------------------------------------------------------
3034 // Timetable editing functions
3035 
3036 /* Note that during early development the timetable was created outside the program as a .csv file using Excel, it was only later that
3037  the editing functions within the program were developed. Much of the original structure was preserved though to avoid rewriting the
3038  code interpretation functions in TrainUnit.cpp. This is why commas are used as service event separators, and why it is necessary to
3039  convert them to CRLFs for display and back again for internal storage. It is acknowledged that all this makes the editing functions
3040  somewhat cumbersome, and, as ever, if I was starting again I wouldn't do it like that!
3041 
3042  CR & LF review:
3043  These cause problems by the way that different subroutines handle them.
3044 
3045  AnsiStrings can incorporate CRLFs, but the end of an AnsiString is marked by a '\0' character as in 'C' strings.
3046 
3047  In the fstream functions 'getline(char_type* s, streamsize n)' extracts characters from the stream and puts them in buffer 's' until
3048  (a) n-1 characters are stored + '\0' after the n-1 characters;
3049  (b) a '\n' (CRLF) character is found in the stream, in which case a '\0' is added to the buffer after the text that immediately
3050  precedes the CRLF in the stream; and
3051  (c) an eof() is found in the stream, in which case a '\0' is added to the buffer at the end of the text.
3052  Note that if no characters are stored a '\0' is still stored in position [0] of the buffer.
3053 
3054  The << operator in ofstreams, when used with a null terminated string, doesn't store the null. If it is required it has to be
3055  sent explicitly, e.g. file << '\0'. Presumably the same applies for CRLF terminated strings.
3056 
3057 */
3058 // ---------------------------------------------------------------------------
3059 
3060 void __fastcall TInterface::CreateTimetableMenuItemClick(TObject *Sender)
3061 {
3062  try
3063  {
3064  TrainController->LogEvent("CreateTimetableMenuItemClick");
3065  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CreateTimetableMenuItemClick");
3066  CreateEditTTFileName = "";
3067  TimetableEditVector.clear();
3068  TimetableEditPanel->Visible = true;
3069  TrainController->TTEditPanelVisible = true; //added at v2.6.0 for two location message
3070  HighlightPanel->Visible = false;
3071  TimetablePanel->Visible = true;
3072  TimetablePanel->BringToFront(); // in case SaveRailway button visible, want it hidden else obscures the panel text
3073  ShowHideTTButton->Glyph->LoadFromResourceName(0, "Hide");
3074  OneEntryTimetableMemo->Clear();
3075  AllEntriesTTListBox->Clear();
3076  TTStartTimeBox->Text = "";
3077  AddSubMinsBox->Text = "";
3079  LocationNameComboBox->Clear();
3080  TimetableTitle = ""; // unload any loaded timetable. Added here at v2.1.0
3081  TrainController->TrainDataVector.clear(); // unload any loaded timetable. Added here at v2.1.0
3082  SetCaption(9); // added at v2.1.0 as formerly retained earlier loaded tt name in error
3083  TimetableChangedFlag = false;
3084  TimetableValidFlag = false;
3085  TTEntryChangedFlag = false;
3087  AZOrderButton->Caption = AnsiString("A-Z Order");
3088  AZOrderButton->Hint = AnsiString("Arrange services in alphabetical order Toggle with Shift+ Z");
3089  CopiedEntryFlag = false;
3090  NewEntryInPreparationFlag = false;
3091  CopiedEntryStr = "";
3092  TEVPtr = 0;
3094  TTFirstServicePtr = 0;
3095  TTLastServicePtr = 0; // all set to null to begin with
3096 
3097 // populate LocationNameComboBox if a railway is loaded, but first compile the ActiveTrackElementNameMap
3098  TTrack::TActiveTrackElementNameMapEntry ActiveTrackElementNameMapEntry;
3100  for(unsigned int x = 0; x < Track->TrackVector.size(); x++)
3101  {
3102  if((Track->TrackVector.at(x).ActiveTrackElementName != "") && (Track->ContinuationNameMap.find(Track->TrackVector.at(x).ActiveTrackElementName))
3103  == Track->ContinuationNameMap.end())
3104  { // exclude any name that appears in a continuation, error message given in tt validation if try to include such a name in a tt
3105  ActiveTrackElementNameMapEntry.first = Track->TrackVector.at(x).ActiveTrackElementName;
3106  ActiveTrackElementNameMapEntry.second = 0; // this is a dummy value
3107  Track->ActiveTrackElementNameMap.insert(ActiveTrackElementNameMapEntry);
3108  }
3109  }
3111  if(!(Track->ActiveTrackElementNameMap.empty()))
3112  {
3113  LocationNameComboBox->Text = "Location names";
3114 // new version at beta v0.2b
3116  ATENIT++)
3117  {
3118  LocationNameComboBox->Items->Add(ATENIT->first); // continuations excluded during compilation, but a location that includes
3119  // continuations as well as other track will be included - earlier version
3120  // would have excluded them
3121  }
3122 
3123 /* old version using LocationNameMultiMap, changed to use ActiveTrackElementNames to avoid including lone concourses and named non-station
3124  locations
3125  TStringList *StringList = new TStringList;
3126  StringList->Clear();//probably already empty but help file doesn't say so
3127  StringList->Sorted = false;//for now
3128  for(TTrack::TLocationNameMultiMapIterator LNMIT = Track->LocationNameMultiMap.begin(); LNMIT != Track->LocationNameMultiMap.end(); LNMIT++)
3129  {
3130  NewKey = LNMIT->first;
3131  if(OldKey != NewKey)//only add new values
3132  {
3133  if(Track->ContinuationNameMap.find(NewKey) == Track->ContinuationNameMap.end())//not a continuation
3134  {
3135  StringList->Add(NewKey);
3136  OldKey = NewKey;
3137  }
3138  }
3139  }
3140  StringList->Sort();
3141  for(int x=0;x<StringList->Count;x++)
3142  {
3143  LocationNameComboBox->Items->Add(StringList->Strings[x]);
3144  }
3145  delete StringList;
3146 */
3147  }
3148  else
3149  {
3150  LocationNameComboBox->Text = "No locations (listed when a railway with names is loaded)";
3151  }
3153  SetLevel1Mode(82);
3154  Utilities->CallLogPop(1595);
3155  }
3156  catch(const Exception &e)
3157  {
3158  ErrorLog(47, e.Message);
3159  }
3160 }
3161 
3162 // ---------------------------------------------------------------------------
3163 void __fastcall TInterface::EditTimetableMenuItemClick(TObject *Sender)
3164 /* The .ttb file contains a sequence of AnsiStrings separated by null characters. CRLFs may be embedded within the AnsiStrings,
3165  * to cause newlines when displayed. Each AnsiString corresponds to a timetable 'entry'
3166 */
3167 {
3168  try
3169  {
3170  TrainController->LogEvent("EditTimetableMenuItemClick");
3171  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",EditTimetableMenuItemClick");
3172  SigImagePanel->Visible = false; //stop panel showing while waiting for name entry
3173  TimetableDialog->Filter = "Timetable file (*.ttb)|*ttb";
3174  CreateEditTTFileName = "";
3175  TimetableEditVector.clear();
3176  TimetableEditPanel->Visible = true;
3177  TrainController->TTEditPanelVisible = true; //added at v2.6.0 for two location message
3178  HighlightPanel->Visible = false;
3179  TimetablePanel->Visible = true;
3180  TimetablePanel->BringToFront(); // in case SaveRailway button visible, want it hidden else obscures the panel text
3181  ShowHideTTButton->Glyph->LoadFromResourceName(0, "Hide");
3182  OneEntryTimetableMemo->Clear();
3183  AllEntriesTTListBox->Clear();
3184  TTStartTimeBox->Text = "";
3185  AddSubMinsBox->Text = "";
3187  LocationNameComboBox->Clear();
3188  TimetableTitle = ""; // unload any loaded timetable. Moved here from below at v2.1.0 for consistency with CreateTimetable
3189  TrainController->TrainDataVector.clear(); // unload any loaded timetable. Moved here from below at v2.1.0 for consistency with CreateTimetable
3190  SetCaption(8); // added at v2.1.0 as formerly retained earlier loaded tt name in error
3191  TEVPtr = 0;
3193  TTFirstServicePtr = 0;
3194  TTLastServicePtr = 0; // all set to null to begin with
3195  if(TimetableDialog->Execute())
3196  {
3197  if(TimetableDialog->InitialDir != TPath::GetDirectoryName(TimetableDialog->FileName))//new at v2.6.0 to retain a new directory
3198  {
3199  TimetableDialog->InitialDir = TPath::GetDirectoryName(TimetableDialog->FileName);
3200  SaveTTDialog->InitialDir = TPath::GetDirectoryName(TimetableDialog->FileName);
3201  }
3202  CreateEditTTFileName = AnsiString(TimetableDialog->FileName);
3203  TrainController->LogEvent("EditTimetable " + CreateEditTTFileName);
3204  std::ifstream TTBLFile(CreateEditTTFileName.c_str(), std::ios_base::binary); // open in binary to examine each character
3205  if(TTBLFile.is_open())
3206  {
3207  // check doesn't contain any non-ascii characters except CR, LF & '\0', and isn't empty
3208  char c;
3209  while(!TTBLFile.eof())
3210  {
3211  TTBLFile.get(c);
3212  if((c < 32) && (c != 13) && (c != 10) && (c != '\0')) // char is signed by default so values > 127 will be caught as treated as -ve
3213  {
3214  ShowMessage("Timetable file is empty or contains non-ascii characters, codes must be between 20 and 127, or CR or LF");
3215  TTBLFile.close();
3216  Utilities->CallLogPop(1612);
3217  return;
3218  }
3219  }
3220  TTBLFile.close();
3221  }
3222  else
3223  {
3224  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
3225  Utilities->CallLogPop(1597);
3226  return;
3227  }
3228  // reopen again in binary mode so the "\r\n" pairs stay as they are rather than being entered as '\n'
3229  Delay(4, 100); // 100mSec delay between closing & re-opening file
3230  TTBLFile.open(CreateEditTTFileName.c_str(), std::ios_base::binary);
3231  if(TTBLFile.is_open())
3232  {
3233  TTBLFile.clear(); // to clear eofbit from last read
3234  TTBLFile.seekg(0); // shouldn't be needed but include for safety
3235  TimetableChangedFlag = false;
3236  TimetableValidFlag = false;
3237  TTEntryChangedFlag = false;
3239  AZOrderButton->Caption = AnsiString("A-Z Order");
3240  AZOrderButton->Hint = AnsiString("Arrange services in alphabetical order Toggle with Shift+ Z");
3241  NewEntryInPreparationFlag = false;
3242  CopiedEntryStr = "";
3243  CopiedEntryFlag = false;
3244 // CreateEditTTFileName = TimetableDialog->FileName;
3245  for(int x = CreateEditTTFileName.Length(); x > 0; x--)
3246  {
3247  if(CreateEditTTFileName[x] == '\\')
3248  {
3249  CreateEditTTTitle = CreateEditTTFileName.SubString(x + 1, CreateEditTTFileName.Length() - x - 4);
3250  break;
3251  }
3252  }
3253  char *TimetableEntryString = new char[10000];
3254  while(true)
3255  {
3256  TTBLFile.getline(TimetableEntryString, 10000, '\0'); // pick up the entire AnsiString, including any embedded newlines
3257  if(TTBLFile.eof() && (TimetableEntryString[0] == '\0')) // stores a null in 1st position if doesn't load any characters
3258  { // may still have eof even if read a line, and
3259  // if so need to process it
3260  break;
3261  }
3262  AnsiString OneLine(TimetableEntryString);
3263  TimetableEditVector.push_back(OneLine);
3264  }
3265  TTBLFile.close();
3266  delete TimetableEntryString;
3267  // here with TimetableEditVector compiled
3268  }
3269  else
3270  {
3271  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
3272  Utilities->CallLogPop(1654);
3273  return;
3274  }
3275  }
3276  else // cancelled dialog [section prior to CallLogPop added for v1.3.2 to clear timetable screen if cancel button pressed]
3277  {
3278  CreateEditTTFileName = "";
3279 // set to null to allow a check during error file saving, if not null save the tt being edited to the file (see entry in ExitTTModeButtonClick)
3280  CreateEditTTTitle = ""; // as above
3281  Level1Mode = BaseMode;
3282  SetLevel1Mode(132);
3283  Utilities->CallLogPop(1633);
3284  return;
3285  }
3286 
3288  if(TimetableEditVector.empty())
3289  {
3291  SetLevel1Mode(89);
3292  Utilities->CallLogPop(1614);
3293  return;
3294  }
3295 
3296 // all now set where can be
3298 
3299 // populate LocationNameComboBox if a railway is loaded, but first compile the ActiveTrackElementNameMap
3300  TTrack::TActiveTrackElementNameMapEntry ActiveTrackElementNameMapEntry;
3302  for(unsigned int x = 0; x < Track->TrackVector.size(); x++)
3303  {
3304  if((Track->TrackVector.at(x).ActiveTrackElementName != "") && (Track->ContinuationNameMap.find(Track->TrackVector.at(x).ActiveTrackElementName))
3305  == Track->ContinuationNameMap.end())
3306  { // exclude any name that appears in a continuation, error message given in tt validation if try to include such a name in a tt
3307  ActiveTrackElementNameMapEntry.first = Track->TrackVector.at(x).ActiveTrackElementName;
3308  ActiveTrackElementNameMapEntry.second = 0; // this is a dummy value
3309  Track->ActiveTrackElementNameMap.insert(ActiveTrackElementNameMapEntry);
3310  }
3311  }
3313  if(!(Track->ActiveTrackElementNameMap.empty()))
3314  {
3315  LocationNameComboBox->Text = "Location names";
3316 // new version for beta v0.2b
3318  ATENIT++)
3319  {
3320  LocationNameComboBox->Items->Add(ATENIT->first); // continuations excluded during compilation, but a location that includes
3321  // continuations as well as other track will be included - earlier version
3322  // would have excluded them
3323  }
3324  }
3325  else
3326  {
3327  LocationNameComboBox->Text = "No locations (listed when a railway with names is loaded)";
3328  }
3330  SetLevel1Mode(83);
3331  Utilities->CallLogPop(1596);
3332  }
3333  catch(const Exception &e)
3334  {
3335  ErrorLog(48, e.Message);
3336  }
3337 }
3338 // ---------------------------------------------------------------------------
3339 
3340 void __fastcall TInterface::ShowHideTTButtonClick(TObject *Sender)
3341 {
3342  try
3343  {
3344  TrainController->LogEvent("ShowHideTTButtonClick");
3345  if(TimetableEditPanel->Visible)
3346  {
3347  ShowHideTTButton->Glyph->LoadFromResourceName(0, "Show");
3348  TimetableEditPanel->Visible = false;
3349  TrainController->TTEditPanelVisible = false; //added at v2.6.0 for two location message
3350  ShowHideTTButton->Hint = "Show the timetable editor Shift S";
3351 // InfoPanel->Visible = false; //changed at v1.3.0 to make it clearer that still in TT mode
3352  InfoPanel->Caption = "Timetable mode: editor hidden"; // as above
3353  }
3354  else
3355  {
3356  ShowHideTTButton->Glyph->LoadFromResourceName(0, "Hide");
3357  TimetableEditPanel->Visible = true;
3358  TrainController->TTEditPanelVisible = true; //added at v2.6.0 for two location message
3359  ShowHideTTButton->Hint = "Hide the timetable editor to see the railway Shift H";
3361  SetLevel1Mode(124);
3362  }
3363  }
3364  catch(const Exception &e)
3365  {
3366  ErrorLog(139, e.Message);
3367  }
3368 }
3369 // ---------------------------------------------------------------------------
3370 
3371 void __fastcall TInterface::NextTTEntryButtonClick(TObject *Sender)
3372 {
3373  try
3374  {
3375  TrainController->LogEvent("NextTTEntryButtonClick");
3376  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",NextTTEntryButtonClick");
3377  if((TTCurrentEntryPtr == 0) || TimetableEditVector.empty())
3378  {
3379  Utilities->CallLogPop(1683);
3380  return;
3381  }
3382  if(TTCurrentEntryPtr < (TimetableEditVector.end() - 1))
3384  TTEntryChangedFlag = false;
3385  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3386  // position changing in AllEntriesTTListBox
3388  SetLevel1Mode(85);
3389  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3390  {
3392  }
3393  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3394  {
3395  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3396  }
3397  else
3398  {
3399  AllEntriesTTListBox->TopIndex = TopPos;
3400  }
3401  Utilities->CallLogPop(1605);
3402  }
3403  catch(const Exception &e)
3404  {
3405  ErrorLog(50, e.Message);
3406  }
3407 }
3408 
3409 // ---------------------------------------------------------------------------
3410 void __fastcall TInterface::PreviousTTEntryButtonClick(TObject *Sender)
3411 {
3412  try
3413  {
3414  TrainController->LogEvent("PreviousTTEntryButtonClick");
3415  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PreviousTTEntryButtonClick");
3416  if((TTCurrentEntryPtr == 0) || TimetableEditVector.empty())
3417  {
3418  Utilities->CallLogPop(1684);
3419  return;
3420  }
3423  TTEntryChangedFlag = false;
3424  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3425  // position changing in AllEntriesTTListBox
3427  SetLevel1Mode(86);
3428  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3429  {
3431  }
3432  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3433  {
3434  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3435  }
3436  else
3437  {
3438  AllEntriesTTListBox->TopIndex = TopPos;
3439  }
3440  Utilities->CallLogPop(1607);
3441  }
3442  catch(const Exception &e)
3443  {
3444  ErrorLog(51, e.Message);
3445  }
3446 }
3447 
3448 // ---------------------------------------------------------------------------
3449 void __fastcall TInterface::NewTTEntryButtonClick(TObject *Sender)
3450 {
3451  try
3452  {
3453  TrainController->LogEvent("NewTTEntryButtonClick");
3454  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",NewTTEntryButtonClick");
3455  OneEntryTimetableMemo->Clear();
3456  OneEntryTimetableMemo->SetFocus();
3459  SetLevel1Mode(103);
3460  Utilities->CallLogPop(1615);
3461  }
3462  catch(const Exception &e)
3463  {
3464  ErrorLog(52, e.Message);
3465  }
3466 }
3467 // ---------------------------------------------------------------------------
3468 
3469 void __fastcall TInterface::AddMinsButtonClick(TObject *Sender)
3470 {
3471  try
3472  {
3473  TrainController->LogEvent("AddMinsButtonClick");
3474  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AddMinsButtonClick");
3475  bool ValidFlag = true;
3476  for(int x = 1; x <= AddSubMinsBox->Text.Length(); x++)
3477  {
3478  if((AddSubMinsBox->Text[x] > '9') || (AddSubMinsBox->Text[x] < '0')) // tested in TTHandler but check here as a safeguard
3479  {
3480  ValidFlag = false;
3481  break;
3482  }
3483  }
3484  if(ValidFlag)
3485  {
3486  if(AddSubMinsBox->Text.ToInt() == 0)
3487  ValidFlag = false;
3488  }
3489  if((TTCurrentEntryPtr == 0) || (*TTCurrentEntryPtr == "") || (AddSubMinsBox->Text == "") || !ValidFlag)
3490  {
3491  Utilities->CallLogPop(1649);
3492  return;
3493  }
3494  TDateTime DummyTime;
3495  int AddMins = AddSubMinsBox->Text.ToInt();
3496  for(int x = 0; x < OneEntryTimetableMemo->Lines->Count; x++)
3497  {
3498  for(int y = 1; y < (OneEntryTimetableMemo->Lines->Strings[x].Length() - 3); y++)
3499  {
3500  if(TrainController->CheckTimeValidity(25, OneEntryTimetableMemo->Lines->Strings[x].SubString(y, 5), DummyTime))
3501  {
3502  int Mins = OneEntryTimetableMemo->Lines->Strings[x].SubString(y + 3, 2).ToInt();
3503  int Hrs = OneEntryTimetableMemo->Lines->Strings[x].SubString(y, 2).ToInt();
3504  Mins += AddMins;
3505  while(Mins >= 60)
3506  {
3507  Mins -= 60;
3508  Hrs++;
3509  }
3510  if(Hrs > 95)
3511  {
3512  ShowMessage("One or more times excessive, not permitted to exceed 95 hours");
3513  Utilities->CallLogPop(1650);
3514  return;
3515  }
3516  AnsiString MinsStr = AnsiString(Mins), HrsStr = AnsiString(Hrs);
3517  if(Mins < 10)
3518  MinsStr = "0" + MinsStr;
3519  if(Hrs < 10)
3520  HrsStr = "0" + HrsStr;
3521  int StrLength = OneEntryTimetableMemo->Lines->Strings[x].Length();
3522  AnsiString NewString = OneEntryTimetableMemo->Lines->Strings[x].SubString(1, (y - 1)); // up to but not including the time
3523  NewString += HrsStr + ':' + MinsStr;
3524  NewString += OneEntryTimetableMemo->Lines->Strings[x].SubString((y + 5), (StrLength - y - 4));
3525  OneEntryTimetableMemo->Lines->Strings[x] = NewString;
3526  }
3527  }
3528  }
3529 
3530  OneEntryTimetableMemo->HideSelection = true;
3531  OneEntryTimetableMemo->SelStart = 0; // need this & next command to set cursor to the top
3532  OneEntryTimetableMemo->SelLength = 0;
3533  TimetableValidFlag = false;
3534  TimetableChangedFlag = true;
3535  TTEntryChangedFlag = true;
3537  SetLevel1Mode(91);
3538  Utilities->CallLogPop(1617);
3539  }
3540  catch(const Exception &e)
3541  {
3542  ErrorLog(54, e.Message);
3543  }
3544 }
3545 // ---------------------------------------------------------------------------
3546 
3547 void __fastcall TInterface::SubMinsButtonClick(TObject *Sender)
3548 {
3549  try
3550  {
3551  TrainController->LogEvent("SubMinsButtonClick");
3552  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SubMinsButtonClick");
3553  bool ValidFlag = true;
3554  for(int x = 1; x <= AddSubMinsBox->Text.Length(); x++)
3555  {
3556  if((AddSubMinsBox->Text[x] > '9') || (AddSubMinsBox->Text[x] < '0')) // tested in TTHandler but check here as a safeguard
3557  {
3558  ValidFlag = false;
3559  break;
3560  }
3561  }
3562  if(ValidFlag)
3563  {
3564  if(AddSubMinsBox->Text.ToInt() == 0)
3565  ValidFlag = false;
3566  }
3567  if((TTCurrentEntryPtr == 0) || (*TTCurrentEntryPtr == "") || (AddSubMinsBox->Text == "") || !ValidFlag)
3568  {
3569  Utilities->CallLogPop(1659);
3570  return;
3571  }
3572  TDateTime DummyTime;
3573  int SubMins = AddSubMinsBox->Text.ToInt();
3574  for(int x = 0; x < OneEntryTimetableMemo->Lines->Count; x++)
3575  {
3576  for(int y = 1; y < (OneEntryTimetableMemo->Lines->Strings[x].Length() - 3); y++)
3577  {
3578  if(TrainController->CheckTimeValidity(28, OneEntryTimetableMemo->Lines->Strings[x].SubString(y, 5), DummyTime))
3579  {
3580  int Mins = OneEntryTimetableMemo->Lines->Strings[x].SubString(y + 3, 2).ToInt();
3581  int Hrs = OneEntryTimetableMemo->Lines->Strings[x].SubString(y, 2).ToInt();
3582  Mins -= SubMins;
3583  while(Mins < 0)
3584  {
3585  Mins += 60;
3586  Hrs--;
3587  }
3588  if(Hrs < 0)
3589  {
3590  ShowMessage("One or more times are now before 00:00, this is not permitted");
3591  Utilities->CallLogPop(1660);
3592  return;
3593  }
3594  AnsiString MinsStr = AnsiString(Mins), HrsStr = AnsiString(Hrs);
3595  if(Mins < 10)
3596  MinsStr = "0" + MinsStr;
3597  if(Hrs < 10)
3598  HrsStr = "0" + HrsStr;
3599  int StrLength = OneEntryTimetableMemo->Lines->Strings[x].Length();
3600  AnsiString NewString = OneEntryTimetableMemo->Lines->Strings[x].SubString(1, (y - 1)); // up to but not including the time
3601  NewString += HrsStr + ':' + MinsStr;
3602  NewString += OneEntryTimetableMemo->Lines->Strings[x].SubString((y + 5), (StrLength - y - 4));
3603  OneEntryTimetableMemo->Lines->Strings[x] = NewString;
3604  }
3605  }
3606  }
3607  OneEntryTimetableMemo->HideSelection = true;
3608  OneEntryTimetableMemo->SelStart = 0; // need this & next command to set cursor to the top
3609  OneEntryTimetableMemo->SelLength = 0;
3610  TimetableValidFlag = false;
3611  TimetableChangedFlag = true;
3612  TTEntryChangedFlag = true;
3614  SetLevel1Mode(92);
3615  Utilities->CallLogPop(1618);
3616  }
3617  catch(const Exception &e)
3618  {
3619  ErrorLog(55, e.Message);
3620  }
3621 }
3622 // ---------------------------------------------------------------------------
3623 
3624 void __fastcall TInterface::CopyTTEntryButtonClick(TObject *Sender)
3625 {
3626  try
3627  {
3628  TrainController->LogEvent("CopyTTEntryButtonClick");
3629  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CopyTTEntryButtonClick");
3630  if(TTCurrentEntryPtr == 0)
3631  {
3632  Utilities->CallLogPop(1636);
3633  return;
3634  }
3636  CopiedEntryFlag = true;
3637  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3638  // position changing in AllEntriesTTListBox
3640  SetLevel1Mode(93);
3641  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3642  {
3644  }
3645  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3646  {
3647  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3648  }
3649  else
3650  {
3651  AllEntriesTTListBox->TopIndex = TopPos;
3652  }
3653  Utilities->CallLogPop(1619);
3654  }
3655  catch(const Exception &e)
3656  {
3657  ErrorLog(56, e.Message);
3658  }
3659 }
3660 // ---------------------------------------------------------------------------
3661 
3662 void __fastcall TInterface::CutTTEntryButtonClick(TObject *Sender)
3663 {
3664  try
3665  {
3666  TrainController->LogEvent("CutTTEntryButtonClick");
3667  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CutTTEntryButtonClick");
3668  if(TTCurrentEntryPtr == 0) // || (*TTCurrentEntryPtr == ""))//safeguard
3669  {
3670  Utilities->CallLogPop(1674);
3671  return;
3672  }
3674  CopiedEntryFlag = true;
3675  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // vector pointers unreliable after an erase,
3676  // so use the position in the vector
3678 // now need to rebuild all the pointers & the AllEntriesTTListBox so repeat the process from EditTimetableMenuItemClick
3679 // pick up the start time if there is one
3680  TimetableChangedFlag = true;
3681  TimetableValidFlag = false;
3682  TTEntryChangedFlag = false;
3683  TEVPtr = 0;
3685  TTFirstServicePtr = 0;
3686  TTLastServicePtr = 0; // all set to null to begin with
3687  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3688  // position changing in AllEntriesTTListBox
3689  AllEntriesTTListBox->Clear();
3691  if(TimetableEditVector.empty())
3692  {
3694  SetLevel1Mode(109);
3695  Utilities->CallLogPop(1777);
3696  return;
3697  }
3698 
3699 // reset the TTCurrentEntryPtr to the Entry before the erased one if there is one //was 'after', changed after v2.4.3
3700 // but vector pointers unreliable after an erase, so use the position in the vector
3701  if(OldVectorPos == 0)
3702  {
3704  }
3705  else
3706  {
3707  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos - 1;
3708  }
3709  if(TTCurrentEntryPtr == 0)
3710  {
3711  OneEntryTimetableMemo->Clear();
3712  }
3714  SetLevel1Mode(115);
3715  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3716  {
3718  }
3719  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3720  {
3721  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3722  }
3723  else
3724  {
3725  AllEntriesTTListBox->TopIndex = TopPos;
3726  }
3727  Utilities->CallLogPop(1676);
3728  }
3729  catch(const Exception &e)
3730  {
3731  ErrorLog(111, e.Message);
3732  }
3733 }
3734 
3735 // ---------------------------------------------------------------------------
3736 void __fastcall TInterface::PasteTTEntryButtonClick(TObject *Sender)
3737 {
3738  try
3739  {
3740  TrainController->LogEvent("PasteTTEntryButtonClick");
3741  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PasteTTEntryButtonClick");
3742  if(TTCurrentEntryPtr == 0) // || (CopiedEntryStr == "")) allow blank copies
3743  {
3744  Utilities->CallLogPop(1637);
3745  return;
3746  }
3747  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // vector pointers unreliable after an insert
3748  TimetableEditVector.insert(TTCurrentEntryPtr + 1, CopiedEntryStr); // inserts before the indicated pointer position, i.e. immediately
3749  // after the current Entry - may be at the end
3750  TimetableChangedFlag = true;
3751  TimetableValidFlag = false;
3752  TTEntryChangedFlag = false;
3753  TEVPtr = 0;
3755  TTFirstServicePtr = 0;
3756  TTLastServicePtr = 0; // all set to null to begin with
3757  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3758  // position changing in AllEntriesTTListBox
3759  AllEntriesTTListBox->Clear();
3761  if(TimetableEditVector.empty())
3762  {
3764  SetLevel1Mode(110);
3765  Utilities->CallLogPop(1778);
3766  return;
3767  }
3768 // restore TTCurrentEntryPtr
3769  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
3770  TTCurrentEntryPtr++; // advance the pointer to the pasted entry
3771 // CopiedEntryStr = "";//revert to null - no, allow multiple copies
3773  SetLevel1Mode(94);
3774  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3775  {
3777  }
3778  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3779  {
3780  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3781  }
3782  else
3783  {
3784  AllEntriesTTListBox->TopIndex = TopPos;
3785  }
3786  Utilities->CallLogPop(1620);
3787  }
3788  catch(const Exception &e)
3789  {
3790  ErrorLog(57, e.Message);
3791  }
3792 }
3793 // ---------------------------------------------------------------------------
3794 
3795 void __fastcall TInterface::DeleteTTEntryButtonClick(TObject *Sender)
3796 {
3797  try
3798  {
3799  TrainController->LogEvent("DeleteTTEntryButtonClick");
3800  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",DeleteTTEntryButtonClick");
3801  if(TTCurrentEntryPtr == 0)
3802  {
3803  Utilities->CallLogPop(1645);
3804  return;
3805  }
3806  UnicodeString MessageStr = "Are you sure this entry should be deleted?";
3807  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
3808  if(button == IDNO)
3809  {
3810  Utilities->CallLogPop(1663);
3811  return;
3812  }
3813  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // vector pointers unreliable after an erase,
3814  // so use the position in the vector
3816 
3817 // now need to rebuild all the pointers & the AllEntriesTTListBox so repeat the process from EditTimetableMenuItemClick
3818 // pick up the start time if there is one
3819  TimetableChangedFlag = true;
3820  TimetableValidFlag = false;
3821  TTEntryChangedFlag = false;
3822  TEVPtr = 0;
3824  TTFirstServicePtr = 0;
3825  TTLastServicePtr = 0; // all set to null to begin with
3826  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3827  // position changing in AllEntriesTTListBox
3828  AllEntriesTTListBox->Clear();
3830  if(TimetableEditVector.empty())
3831  {
3833  SetLevel1Mode(111);
3834  Utilities->CallLogPop(1779);
3835  return;
3836  }
3837 // reset the TTCurrentEntryPtr to the Entry before the erased one if there is one
3838 // but vector pointers unreliable after an erase, so use the position in the vector
3839  if(OldVectorPos == 0)
3840  {
3842  }
3843  else
3844  {
3845  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos - 1;
3846  }
3847  if(TTCurrentEntryPtr == 0)
3848  {
3849  OneEntryTimetableMemo->Clear();
3850  }
3852  SetLevel1Mode(95);
3853  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
3854  {
3856  }
3857  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
3858  {
3859  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
3860  }
3861  else
3862  {
3863  AllEntriesTTListBox->TopIndex = TopPos;
3864  }
3865  Utilities->CallLogPop(1621);
3866  }
3867  catch(const Exception &e)
3868  {
3869  ErrorLog(58, e.Message);
3870  }
3871 }
3872 // ---------------------------------------------------------------------------
3873 
3874 void __fastcall TInterface::SaveTTEntryButtonClick(TObject *Sender)
3875 {
3876  try
3877  {
3878  TrainController->LogEvent("SaveTTEntryButtonClick");
3879  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveTTEntryButtonClick");
3880 /* allow blank lines to be saved
3881  AnsiString ContentStr = OneEntryTimetableMemo->Text;
3882  if((ContentStr == "\r\n") || (ContentStr == "\n") || (ContentStr == ""))
3883  {
3884  Utilities->CallLogPop(1679);
3885  return;
3886  }
3887 */
3888  AnsiString TempStr = "";
3889  bool ActiveLine = false;
3890  if(TTCurrentEntryPtr > 0)
3891  {
3892  if(*TTCurrentEntryPtr != "")
3893  {
3895  {
3896  ActiveLine = true;
3897  // need to add commas after each line in OneEntryTimetableMemo exept the last, where have '\0'
3898  for(int x = 0; x < OneEntryTimetableMemo->Lines->Count; x++)
3899  {
3900  for(int y = 1; y <= OneEntryTimetableMemo->Lines->Strings[x].Length(); y++)
3901  {
3902  TempStr += OneEntryTimetableMemo->Lines->Strings[x][y];
3903  }
3904  if(x < (OneEntryTimetableMemo->Lines->Count - 1))
3905  {
3906  TempStr += ',';
3907  }
3908  // No need to add a '\n' as a '\0' is added automatically as a string delimiter. If add '\n' then it is treated as a blank line and
3909  // ends the timetable
3910  }
3911  // strip any excess commas from the end
3912  if(TempStr != "")
3913  {
3914  while(TempStr[TempStr.Length()] == ',')
3915  {
3916  TempStr = TempStr.SubString(1, TempStr.Length() - 1);
3917  if(TempStr == "")
3918  break;
3919  }
3920  }
3921  }
3922  }
3923  }
3924  if(!ActiveLine)
3925  {
3926  TempStr = OneEntryTimetableMemo->Text; // Note that if the entry was intended as a service but goes in as plain text because
3927  // the service & entry pointers aren't yet set, then CRLFs will be converted to commas in
3928  // CompileAllEntriesMemoAndSetPointers if it appears after the start time
3929  // and before a blank line or end of file, so the syntax check will work OK
3930  }
3931  if(AZOrderButton->Caption == AnsiString("Original Order"))
3932  {
3934  }
3935  TimetableValidFlag = false;
3936  TimetableChangedFlag = true;
3937  TTEntryChangedFlag = false;
3938  int TopPos;
3939  if(TTCurrentEntryPtr == 0)
3940  {
3942  }
3944  {
3945  (*TTCurrentEntryPtr) = TempStr;
3946  // need to reset the AllEntriesTTListBox in case the headcode has changed
3947  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // vector pointers unreliable after an insert
3948  TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3949  // position changing in AllEntriesTTListBox
3950  AllEntriesTTListBox->Clear();
3952  if(TimetableEditVector.empty())
3953  {
3955  SetLevel1Mode(112);
3956  Utilities->CallLogPop(1780);
3957  return;
3958  }
3959  // restore TTCurrentEntryPtr
3960  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
3961  }
3962  else
3963  {
3964  NewEntryInPreparationFlag = false;
3965  if(TTCurrentEntryPtr != 0)
3966  {
3967  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // vector pointers unreliable after an insert
3968  TimetableEditVector.insert(TTCurrentEntryPtr + 1, TempStr); // inserts before the indicated pointer position, which may be at the end
3969  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
3971  }
3972  else
3973  {
3974  TimetableEditVector.insert(TimetableEditVector.end(), TempStr); // inserts before the indicated pointer position
3976  }
3977  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // save the current position
3978  TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
3979  // position changing in AllEntriesTTListBox
3980  AllEntriesTTListBox->Clear();
3982  if(TimetableEditVector.empty())
3983  {
3985  SetLevel1Mode(113);
3986  Utilities->CallLogPop(1781);
3987  return;
3988  }
3989 // reset the TTCurrentEntryPtr after CompileAllEntriesMemoAndSetPointers
3990  if(OldVectorPos >= TimetableEditVector.end() - TimetableEditVector.begin() - 1)
3991  {
3993  }
3994  else
3995  {
3996  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
3997  }
3998  }
4000  SetLevel1Mode(96);
4001  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
4002  {
4004  }
4005  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
4006  {
4007  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
4008  }
4009  else
4010  {
4011  AllEntriesTTListBox->TopIndex = TopPos;
4012  }
4013  Utilities->CallLogPop(1622);
4014  }
4015  catch(const Exception &e)
4016  {
4017  ErrorLog(59, e.Message);
4018  }
4019 }
4020 // ---------------------------------------------------------------------------
4021 
4022 void __fastcall TInterface::SaveTTButtonClick(TObject *Sender)
4023 {
4024  try
4025  {
4026  TrainController->LogEvent("SaveTTButtonClick");
4027  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveTTButtonClick");
4028  if(TimetableEditVector.empty())
4029  {
4030  ShowMessage("Timetable is empty, can't save an empty timetable");
4031  Utilities->CallLogPop(1685);
4032  return;
4033  }
4034  std::ofstream TTBLFile;
4035  if(CreateEditTTFileName != "")
4036  {
4037  TTBLFile.open(CreateEditTTFileName.c_str(), std::ios_base::binary); // if text then each time sees a "\r\n" pair enters "\r\n\n" because '\n'
4038  // on its own causes "\r\n' to ne inserted, binary just enters characters as they are
4039  }
4040  else
4041  {
4042  if(SaveTTDialog->Execute())
4043  {
4044  if(SaveTTDialog->InitialDir != TPath::GetDirectoryName(SaveTTDialog->FileName))//new at v2.6.0 to retain a new directory
4045  {
4046  TimetableDialog->InitialDir = TPath::GetDirectoryName(SaveTTDialog->FileName);
4047  SaveTTDialog->InitialDir = TPath::GetDirectoryName(SaveTTDialog->FileName);
4048  }
4049  CreateEditTTFileName = AnsiString(SaveTTDialog->FileName);
4050  for(int x = CreateEditTTFileName.Length(); x > 0; x--)
4051  {
4052  if(CreateEditTTFileName[x] == '\\')
4053  {
4054  CreateEditTTTitle = CreateEditTTFileName.SubString(x + 1, CreateEditTTFileName.Length() - x - 4);
4055  break;
4056  }
4057  }
4058  TTBLFile.open(CreateEditTTFileName.c_str(), std::ios_base::binary); // if text then each time sees a "\r\n" pair enters "\r\n\n" because '\n'
4059  // on its own causes "\r\n' to ne inserted, binary just enters characters as they are
4060  }
4061  else //cancelled dialog
4062  {
4064  SetLevel1Mode(137);
4065  Utilities->CallLogPop(2205);
4066  return;
4067  }
4068  }
4069  if(TTBLFile.is_open())
4070  {
4071  for(TEVPtr = TimetableEditVector.begin(); TEVPtr != TimetableEditVector.end(); TEVPtr++)
4072  {
4073  TTBLFile << (*TEVPtr).c_str() << '\0';
4074  }
4075  TimetableChangedFlag = false;
4076  TTBLFile.close();
4077  }
4078  else
4079  {
4080  ShowMessage(CreateEditTTFileName + " failed to open, ensure not already open in another application");
4081  }
4083  SetLevel1Mode(97);
4084  Utilities->CallLogPop(1623);
4085  }
4086  catch(const Exception &e)
4087  {
4088  ErrorLog(60, e.Message);
4089  }
4090 }
4091 // ---------------------------------------------------------------------------
4092 
4093 void __fastcall TInterface::SaveTTAsButtonClick(TObject *Sender)
4094 {
4095  try
4096  {
4097  TrainController->LogEvent("SaveTTAsButtonClick");
4098  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SaveTTAsButtonClick");
4099  if(TimetableEditVector.empty())
4100  {
4101  ShowMessage("Timetable is empty, can't save an empty timetable");
4102  Utilities->CallLogPop(1686);
4103  return;
4104  }
4105  std::ofstream TTBLFile;
4106  if(SaveTTDialog->Execute())
4107  {
4108  if(SaveTTDialog->InitialDir != TPath::GetDirectoryName(SaveTTDialog->FileName))//new at v2.6.0 to retain a new directory
4109  {
4110  TimetableDialog->InitialDir = TPath::GetDirectoryName(SaveTTDialog->FileName);
4111  SaveTTDialog->InitialDir = TPath::GetDirectoryName(SaveTTDialog->FileName);
4112  }
4113  CreateEditTTFileName = SaveTTDialog->FileName;
4114  for(int x = SaveTTDialog->FileName.Length(); x > 0; x--)
4115  {
4116  if(SaveTTDialog->FileName[x] == '\\')
4117  {
4118  CreateEditTTTitle = SaveTTDialog->FileName.SubString(x + 1, SaveTTDialog->FileName.Length() - x - 4);
4119  break;
4120  }
4121  }
4122  TTBLFile.open(CreateEditTTFileName.c_str(), std::ios_base::binary); // if text then each time sees a "\r\n" pair enters "\r\n\n" because '\n'
4123  // on its own causes "\r\n' to ne inserted, binary just enters characters as they are
4124  }
4125  else //cancelled dialog
4126  {
4128  SetLevel1Mode(138);
4129  Utilities->CallLogPop(2206);
4130  return;
4131  }
4132  if(TTBLFile.is_open())
4133  {
4134  for(TEVPtr = TimetableEditVector.begin(); TEVPtr != TimetableEditVector.end(); TEVPtr++)
4135  {
4136  TTBLFile << (*TEVPtr).c_str() << '\0';
4137  }
4138  TimetableChangedFlag = false;
4139  TTBLFile.close();
4140  }
4141  else
4142  {
4143  ShowMessage(CreateEditTTFileName + " failed to open, ensure not already open in another application");
4144  }
4146  SetLevel1Mode(117);
4147  Utilities->CallLogPop(1667);
4148  }
4149  catch(const Exception &e)
4150  {
4151  ErrorLog(108, e.Message);
4152  }
4153 }
4154 // ---------------------------------------------------------------------------
4155 
4156 void __fastcall TInterface::TTServiceSyntaxCheckButtonClick(TObject *Sender)
4157 {
4158  try
4159  {
4160  TrainController->LogEvent("TTServiceSyntaxCheckButtonClick");
4161  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTServiceSyntaxCheckButtonClick");
4162  int Count = 1; // anything > 0 OK as if 0 still seeking a start time
4163  bool EndOfFile = false;
4164  bool FinalCallFalse = false;
4165  bool GiveMessagesTrue = true;
4166  bool CheckLocationsExistInRailway = false;
4167  if(RlyFile)
4168  CheckLocationsExistInRailway = true;
4169 // TrainController->AnyHeadCodeValid = true; //don't fail here because of an unrestricted headcode, if no good will find when validate (dropped at v0.6b)
4170  if(TrainController->ProcessOneTimetableLine(2, Count, *TTCurrentEntryPtr, EndOfFile, FinalCallFalse, GiveMessagesTrue, CheckLocationsExistInRailway))
4171  // return true for success
4172  {
4173  ShowMessage(
4174  "The basic syntax seems OK but this check is very limited. Other aspects can only be checked by validating the whole timetable with the appropriate railway (.rly) loaded");
4175  }
4177  SetLevel1Mode(98);
4178  Utilities->CallLogPop(1624);
4179  }
4180  catch(const Exception &e)
4181  {
4182  ErrorLog(61, e.Message);
4183  }
4184 }
4185 // ---------------------------------------------------------------------------
4186 
4187 void __fastcall TInterface::ValidateTimetableButtonClick(TObject *Sender)
4188 {
4189  try
4190  {
4191  TrainController->LogEvent("ValidateTimetableButtonClick");
4192  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ValidateTimetableButtonClick");
4193  // reset all message flags, stops them being given twice new at v2.4.0
4194  TrainController->SSHigh = false;
4195  TrainController->MRSHigh = false;
4196  TrainController->MRSLow = false;
4197  TrainController->MassHigh = false;
4198  TrainController->BFHigh = false;
4199  TrainController->BFLow = false;
4200  TrainController->PwrHigh = false;
4201  TrainController->SigSHigh = false;
4202  TrainController->SigSLow = false;
4203  if(CreateEditTTFileName == "")
4204  {
4205  Utilities->CallLogPop(1664);
4206  return;
4207  }
4208  bool CheckLocationsExistInRailwayTrue = true;
4209  if(TrainController->TimetableIntegrityCheck(2, CreateEditTTFileName.c_str(), true, CheckLocationsExistInRailwayTrue)) // messages = true
4210  {
4211  Screen->Cursor = TCursor(-11); // Hourglass;
4212  std::ifstream TTBLFile(CreateEditTTFileName.c_str(), std::ios_base::binary);
4213  if(TTBLFile.is_open())
4214  {
4215  if(BuildTrainDataVectorForValidateFile(0, TTBLFile, true, CheckLocationsExistInRailwayTrue)) // messages = true
4216  {
4217  ShowMessage("Timetable integrity OK");
4218  TimetableValidFlag = true;
4219 // TrainController->TrainDataVector.clear(); keep this so can export a formatted tt
4220  };
4221  }
4222  else
4223  {
4224  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
4225  }
4226  Screen->Cursor = TCursor(-2); // Arrow
4227  } // if(TimetableIntegrityCheck
4228  else
4229  {
4230 // ShowMessage("Timetable preliminary integrity check failed"); dropped in v2.4.0 as messages given in all called functions
4231  }
4233  SetLevel1Mode(99);
4234  Utilities->CallLogPop(1625);
4235  }
4236  catch(const Exception &e)
4237  {
4238  ErrorLog(62, e.Message);
4239  }
4240 }
4241 
4242 // ---------------------------------------------------------------------------
4243 void __fastcall TInterface::MoveTTEntryUpButtonClick(TObject *Sender)
4244 {
4245  try
4246  {
4247  TrainController->LogEvent("MoveTTEntryUpButtonClick");
4248  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MoveTTEntryUpButtonClick");
4249  if(TTCurrentEntryPtr == 0)
4250  {
4251  Utilities->CallLogPop(1634);
4252  return;
4253  }
4254  if(TTCurrentEntryPtr < (TimetableEditVector.begin() + 1)) // shouldn't reach here but return if do
4255  {
4256  Utilities->CallLogPop(1632);
4257  return;
4258  }
4259  TEVPtr = TTCurrentEntryPtr - 1; // find earlier Entry
4260  AnsiString TempStr = *TEVPtr;
4262  *TTCurrentEntryPtr = TempStr;
4264  TimetableChangedFlag = true;
4265  TimetableValidFlag = false;
4266 
4267 // now rebuild AllEntriesTTListBox, DisplayOneTTLineInPanel will highlight it
4268  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
4269  // position changing in AllEntriesTTListBox
4270  AllEntriesTTListBox->Clear();
4271  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // save the old position
4273 // reset the TTCurrentEntryPtr after CompileAllEntriesMemoAndSetPointers
4274  if(OldVectorPos >= TimetableEditVector.end() - TimetableEditVector.begin() - 1)
4275  {
4277  }
4278  else
4279  {
4280  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
4281  }
4283  SetLevel1Mode(100);
4284  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
4285  {
4287  }
4288  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
4289  {
4290  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
4291  }
4292  else
4293  {
4294  AllEntriesTTListBox->TopIndex = TopPos;
4295  }
4296  Utilities->CallLogPop(1626);
4297  }
4298  catch(const Exception &e)
4299  {
4300  ErrorLog(63, e.Message);
4301  }
4302 }
4303 // ---------------------------------------------------------------------------
4304 
4305 void __fastcall TInterface::MoveTTEntryDownButtonClick(TObject *Sender)
4306 {
4307  try
4308  {
4309  TrainController->LogEvent("MoveTTEntryDownButtonClick");
4310  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MoveTTEntryDownButtonClick");
4311  if(TTCurrentEntryPtr == 0)
4312  {
4313  Utilities->CallLogPop(1635);
4314  return;
4315  }
4316  if(TTCurrentEntryPtr >= (TimetableEditVector.end() - 1)) // shouldn't reach here but return if do
4317  {
4318  Utilities->CallLogPop(1678);
4319  return;
4320  }
4321  TEVPtr = TTCurrentEntryPtr + 1; // find later Entry
4322  AnsiString TempStr = *TEVPtr;
4324  *TTCurrentEntryPtr = TempStr;
4326  TimetableChangedFlag = true;
4327  TimetableValidFlag = false;
4328 
4329 // now rebuild AllEntriesTTListBox, DisplayOneTTLineInPanel will highlight it
4330  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
4331  // position changing in AllEntriesTTListBox
4332  AllEntriesTTListBox->Clear();
4333  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // save the old position
4335 // reset the TTCurrentEntryPtr after CompileAllEntriesMemoAndSetPointers
4336  if(OldVectorPos >= TimetableEditVector.end() - TimetableEditVector.begin() - 1)
4337  {
4339  }
4340  else
4341  {
4342  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
4343  }
4345  SetLevel1Mode(101);
4346  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
4347  {
4349  }
4350  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
4351  {
4352  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
4353  }
4354  else
4355  {
4356  AllEntriesTTListBox->TopIndex = TopPos;
4357  }
4358  Utilities->CallLogPop(1627);
4359  }
4360  catch(const Exception &e)
4361  {
4362  ErrorLog(64, e.Message);
4363  }
4364 }
4365 
4366 // ---------------------------------------------------------------------------
4367 void __fastcall TInterface::CancelTTEntryButtonClick(TObject *Sender)
4368 {
4369  try
4370  {
4371  TrainController->LogEvent("CancelTTActionButtonClick");
4372  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CancelTTActionButtonClick");
4373  TTEntryChangedFlag = false;
4375  {
4376  NewEntryInPreparationFlag = false;
4377  OneEntryTimetableMemo->Clear();
4378  }
4379  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
4380  // position changing in AllEntriesTTListBox
4382  SetLevel1Mode(102);
4383  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < TopPos)
4384  {
4386  }
4387  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (TopPos + 45))
4388  {
4389  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
4390  }
4391  else
4392  {
4393  AllEntriesTTListBox->TopIndex = TopPos;
4394  }
4395  Utilities->CallLogPop(1630);
4396  }
4397  catch(const Exception &e)
4398  {
4399  ErrorLog(102, e.Message);
4400  }
4401 }
4402 
4403 // ---------------------------------------------------------------------------
4404 void __fastcall TInterface::RestoreTTButtonClick(TObject *Sender)
4405 {
4406  try
4407  {
4408  TrainController->LogEvent("RestoreTTButtonClick");
4409  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RestoreTTButtonClick");
4411  {
4412  UnicodeString MessageStr = "All changes to the timetable will be lost - proceed?";
4413  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
4414  if(button == IDNO)
4415  {
4416  Utilities->CallLogPop(1651);
4417  return;
4418  }
4419  }
4420 
4421  // repeat from EditTimetableMenuItemClick, but no need to check for non-ascii characters
4422  // open in binary mode so the "\r\n" pairs stay as they are rather than being entered as '\n'
4423  std::ifstream TTBLFile(CreateEditTTFileName.c_str(), std::ios_base::binary);
4424  if(TTBLFile.is_open())
4425  {
4426  TimetableChangedFlag = false;
4427  TimetableValidFlag = false;
4428  TTEntryChangedFlag = false;
4429  NewEntryInPreparationFlag = false;
4430  CopiedEntryFlag = false;
4431  CopiedEntryStr = "";
4432  TimetableEditVector.clear();
4433  OneEntryTimetableMemo->Clear();
4434  AllEntriesTTListBox->Clear();
4435  TTStartTimeBox->Text = "";
4436  AddSubMinsBox->Text = "";
4437  TEVPtr = 0;
4439  TTFirstServicePtr = 0;
4440  TTLastServicePtr = 0; // all set to null to begin with
4441  char *TimetableEntryString = new char[10000];
4442  while(true)
4443  {
4444  TTBLFile.getline(TimetableEntryString, 10000, '\0'); // pick up the entire AnsiString, including any embedded newlines
4445  if(TTBLFile.eof() && (TimetableEntryString[0] == '\0')) // stores a null in 1st position if doesn't load any characters
4446  { // may still have eof even if read a line, and
4447  // if so need to process it
4448  break;
4449  }
4450  AnsiString OneLine(TimetableEntryString);
4451  TimetableEditVector.push_back(OneLine);
4452  }
4453  TTBLFile.close();
4454  delete TimetableEntryString;
4455  // here with TimetableEditVector compiled
4456  }
4457  else
4458  {
4459  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
4460  Utilities->CallLogPop(1655);
4461  return;
4462  }
4463 
4465  if(TimetableEditVector.empty())
4466  {
4468  SetLevel1Mode(114);
4469  Utilities->CallLogPop(1782);
4470  return;
4471  }
4472 // all now set where can be
4474 // end of repeat from EditTimetableMenuItemClick
4475 
4477  SetLevel1Mode(104);
4478  Utilities->CallLogPop(1652);
4479  }
4480  catch(const Exception &e)
4481  {
4482  ErrorLog(104, e.Message);
4483  }
4484 }
4485 
4486 // ---------------------------------------------------------------------------
4487 void __fastcall TInterface::ExportTTButtonClick(TObject *Sender)
4488 {
4489  try
4490  {
4491  TrainController->LogEvent("ExportTTButtonClick");
4492  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExportTTButtonClick");
4493  if(!DirectoryExists(CurDir + "\\" + FORMATTEDTT_DIR_NAME))
4494  {
4495  ShowMessage("Failed to find folder " + FORMATTEDTT_DIR_NAME + " in the folder where 'railway.exe' resides. Timetable can't be exported");
4496  Utilities->CallLogPop(1698);
4497  return;
4498  }
4499 // Screen->Cursor = TCursor(-11); // Hourglass; - no good setting here as it's reset by ShowMessage in CreateFormattedTimetable. It's set there after
4500 // the message instead, but reset here afterwards
4501  AnsiString TTTitle;
4503  {
4504  for(int x = CreateEditTTFileName.Length(); x > 0; x--) // first need to strip out the timetable title from the full name
4505  {
4506  if(CreateEditTTFileName[x] == '\\')
4507  {
4508  TTTitle = CreateEditTTFileName.SubString(x + 1, CreateEditTTFileName.Length() - x - 4);
4509  break;
4510  }
4511  }
4513  }
4514  Screen->Cursor = TCursor(-2); // Arrow - reset after above function returns
4516  SetLevel1Mode(116);
4517  Utilities->CallLogPop(1662);
4518  }
4519  catch(const Exception &e)
4520  {
4521  ErrorLog(107, e.Message);
4522  }
4523 }
4524 
4525 // ---------------------------------------------------------------------------
4526 void __fastcall TInterface::TTTextButtonClick(TObject *Sender)
4527 {
4528  try
4529  {
4530  TrainController->LogEvent("TTTextButtonClick");
4531  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTTextButtonClick");
4532 /*
4533  if(TTStartTimePtr == 0)
4534  {
4535  OneEntryTimetableMemo->Clear();
4536  TTStartTimeBox->SetFocus();
4537  Utilities->CallLogPop(1673);
4538  return;
4539  }
4540 */
4541  int SelPos = OneEntryTimetableMemo->SelStart;
4542  AnsiString FirstPart = OneEntryTimetableMemo->Text.SubString(1, SelPos);
4543  AnsiString LastPart = OneEntryTimetableMemo->Text.SubString(SelPos + 1, OneEntryTimetableMemo->Text.Length() - SelPos);
4544  OneEntryTimetableMemo->Text = FirstPart + ((TButton*)Sender)->Caption + LastPart;
4545  OneEntryTimetableMemo->SelStart = SelPos + ((TButton*)Sender)->Caption.Length();
4546  TTEntryChangedFlag = true;
4547  OneEntryTimetableMemo->SetFocus();
4549  SetLevel1Mode(119);
4550  Utilities->CallLogPop(1672);
4551  }
4552  catch(const Exception &e)
4553  {
4554  ErrorLog(110, e.Message);
4555  }
4556 }
4557 
4558 // ---------------------------------------------------------------------------
4559 void __fastcall TInterface::ExitTTModeButtonClick(TObject *Sender)
4560 {
4561  try
4562  {
4563  TrainController->LogEvent("ExitTTCreateEditButtonClick");
4564  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExitTTCreateEditButtonClick");
4566  {
4567  UnicodeString MessageStr = "The timetable has changed.\n\nAre you sure you want to exit without saving it?";
4568  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
4569  if(button == IDNO)
4570  {
4571  Utilities->CallLogPop(1603);
4572  return;
4573  }
4574  }
4575  TimetableChangedFlag = false;
4576  CreateEditTTFileName = ""; // set to null to allow a check during error file saving, if not null save the tt being edited to the file
4577  // added for Beta v0.2b
4578  CreateEditTTTitle = ""; // as above
4579  ConflictPanel->Visible = false;
4580  Level1Mode = BaseMode;
4581  SetLevel1Mode(84);
4582  Utilities->CallLogPop(1606);
4583  }
4584  catch(const Exception &e)
4585  {
4586  ErrorLog(49, e.Message);
4587  }
4588 }
4589 
4590 // ---------------------------------------------------------------------------
4591 void __fastcall TInterface::LocationNameComboBoxClick(TObject *Sender)
4592 {
4593  try
4594  {
4595  TrainController->LogEvent("LocationNameComboBoxClick");
4596  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LocationNameComboBoxClick");
4597  if(TTStartTimePtr != 0)
4598  {
4599  LocationNameComboBox->SelectAll();
4600  int SelPos = OneEntryTimetableMemo->SelStart;
4601  AnsiString FirstPart = OneEntryTimetableMemo->Text.SubString(1, SelPos);
4602  AnsiString LastPart = OneEntryTimetableMemo->Text.SubString(SelPos + 1, OneEntryTimetableMemo->Text.Length() - SelPos);
4603  OneEntryTimetableMemo->Text = FirstPart + LocationNameComboBox->SelText + LastPart;
4604  OneEntryTimetableMemo->SelStart = SelPos + LocationNameComboBox->SelText.Length();
4605  TTEntryChangedFlag = true;
4606  OneEntryTimetableMemo->SetFocus();
4608  SetLevel1Mode(118);
4609  }
4610  Utilities->CallLogPop(1669);
4611  }
4612  catch(const Exception &e)
4613  {
4614  ErrorLog(109, e.Message);
4615  }
4616 }
4617 
4618 // ---------------------------------------------------------------------------
4619 void __fastcall TInterface::OneEntryTimetableMemoKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
4620 {
4621  try
4622  {
4623 // TrainController->LogEvent("OneEntryTimetableMemoKeyUp"); drop this - too many entries
4624  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OneEntryTimetableMemoKeyUp");
4626  {
4627  Utilities->CallLogPop(1716);
4628  return;
4629  }
4630  TimetableChangedFlag = true;
4631  TTEntryChangedFlag = true;
4632  TimetableValidFlag = false;
4634  SetLevel1Mode(127);
4635  Utilities->CallLogPop(1629);
4636  }
4637  catch(const Exception &e)
4638  {
4639  ErrorLog(66, e.Message);
4640  }
4641 }
4642 
4643 // ---------------------------------------------------------------------------
4644 void __fastcall TInterface::AddSubMinsBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
4645 {
4646 // forces a recheck for whether addmins/submins buttons should be enabled
4647  try
4648  {
4649  TrainController->LogEvent("AddSubMinsBoxKeyUp");
4650  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AddSubMinsBoxKeyUp");
4652  SetLevel1Mode(108);
4653  Utilities->CallLogPop(1658);
4654  }
4655  catch(const Exception &e)
4656  {
4657  ErrorLog(106, e.Message);
4658  }
4659 }
4660 
4661 // ---------------------------------------------------------------------------
4662 void __fastcall TInterface::LocationNameComboBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
4663 {
4664  try
4665  {
4666  TrainController->LogEvent("LocationNameComboBoxKeyUp");
4667  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LocationNameComboBoxKeyUp");
4668  if(!Track->LocationNameMultiMap.empty())
4669  {
4670  LocationNameComboBox->Text = "Location names";
4671  }
4672  else
4673  {
4674  LocationNameComboBox->Text = "No locations (listed when a railway with names is loaded)";
4675  }
4676  Utilities->CallLogPop(1677);
4677  }
4678  catch(const Exception &e)
4679  {
4680  ErrorLog(112, e.Message);
4681  }
4682 }
4683 
4684 // ---------------------------------------------------------------------------
4685 
4686 void __fastcall TInterface::AllEntriesTTListBoxMouseUp(TObject *Sender, TMouseButton Button,
4687  TShiftState Shift, int X, int Y)
4688 {
4689 // Select the item pointed to unless a 'save entry' is pending in which case ignore
4690  try
4691  {
4692  TrainController->LogEvent("AllEntriesTTListBoxMouseUp," + AnsiString(X) + "," + AnsiString(Y));
4693  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AllEntriesTTListBoxMouseUp," + AnsiString(X) + "," + AnsiString(Y));
4694  if((TTCurrentEntryPtr == 0) || TimetableEditVector.empty())
4695  {
4696  Utilities->CallLogPop(1687);
4697  return;
4698  }
4699  if(TTEntryChangedFlag || NewEntryInPreparationFlag) // if a save/cancel pending don't permit anything else
4700  {
4701  Utilities->CallLogPop(1688);
4702  return;
4703  }
4704  // find item required - 13 pixels per line of text
4705  int TopPos = AllEntriesTTListBox->TopIndex; // need to store this & reset it after SetLevel1Mode to prevent the scroll
4706  // position changing in AllEntriesTTListBox
4707  if((TopPos + (Y / 13)) >= AllEntriesTTListBox->Items->Count)
4708  {
4710  }
4711  else
4712  {
4713  TTCurrentEntryPtr = TimetableEditVector.begin() + (Y / 13) + TopPos;
4714  }
4715  int OldVectorPos = TTCurrentEntryPtr - TimetableEditVector.begin(); // save the old position
4717 // reset the TTCurrentEntryPtr after CompileAllEntriesMemoAndSetPointers
4718  if(OldVectorPos >= TimetableEditVector.end() - TimetableEditVector.begin() - 1)
4719  {
4721  }
4722  else
4723  {
4724  TTCurrentEntryPtr = TimetableEditVector.begin() + OldVectorPos;
4725  }
4727  SetLevel1Mode(120);
4728  AllEntriesTTListBox->TopIndex = TopPos; // reset it after SetLevel1Mode to prevent the scroll position changing
4729  Utilities->CallLogPop(1648);
4730  }
4731  catch(const Exception &e)
4732  {
4733  ErrorLog(103, e.Message);
4734  }
4735 }
4736 
4737 // ---------------------------------------------------------------------------
4738 
4739 void __fastcall TInterface::OAListBoxMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
4740 {
4741 // Mouseup rather than Mousedown so shows floating label when over train
4742  try
4743  {
4744  TrainController->LogEvent("OAListBoxMouseUp," + AnsiString(X) + "," + AnsiString(Y));
4745  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OAListBoxMouseUp," + AnsiString(X) + "," + AnsiString(Y));
4746  if(Track->RouteFlashFlag || Track->PointFlashFlag) // no action
4747  {
4748  Utilities->CallLogPop(2087);
4749  return;
4750  }
4752  {
4753  Utilities->CallLogPop(2088);
4754  return;
4755  }
4757  // find item required - 13 pixels per line of text
4758  int TopPos = OAListBox->TopIndex;
4759  int OAIndex;
4760  if((TopPos + (Y / 13)) >= OAListBox->Items->Count) // if click beyond end of list ignore
4761  {
4762  Utilities->CallLogPop(2089);
4763  return;
4764  }
4765  else
4766  {
4767  OACurrentEntryPtr = TrainController->OpTimeToActMultiMap.begin();
4768  std::advance(OACurrentEntryPtr, ((Y / 13) + TopPos));
4769  }
4770  int HPos;
4771  int VPos;
4772  int TrackVectorPosition;
4773  int TrainIDorTVPos = OACurrentEntryPtr->second.second;
4774  if(TrainIDorTVPos >= 0) // running train, so value is the TrainID
4775  {
4776  if(TrainController->TrainExistsAtIdent(0, TrainIDorTVPos)) // added at v2.4.0 in case train removed but still in OA list as not updated yet
4777  // see LiWinDom error report on Discord 23/04/20. Also needed for click OAListBox before any trains show,
4778  // as notified by Rokas Serys by email on 16/05/20
4779  {
4780  TrackVectorPosition = TrainController->TrainVectorAtIdent(43, TrainIDorTVPos).LeadElement;
4781  }
4782  else
4783  {
4784  Utilities->CallLogPop(2155); // if not there then ignore
4785  return;
4786  }
4787  }
4788  else // train to enter at a continuation, so value is -TVPos of continuation - 1
4789  {
4790  TrackVectorPosition = -(TrainIDorTVPos + 1);
4791  }
4792  HPos = (Track->TrackElementAt(926, TrackVectorPosition).HLoc * 16);
4793  VPos = (Track->TrackElementAt(927, TrackVectorPosition).VLoc * 16);
4794  // now want to set the offsets to display HPos & VPos in the centre of the screen
4795  Display->DisplayOffsetH = (HPos - MainScreen->Width / 2) / 16; // ScreenPosH = HPos - (DisplayOffsetH * 16)
4796  Display->DisplayOffsetV = (VPos - MainScreen->Height / 2) / 16;
4797  int ScreenPosH = HPos - (Display->DisplayOffsetH * 16);
4798  int ScreenPosV = VPos - (Display->DisplayOffsetV * 16);
4799  if(Display->ZoomOutFlag) // panel displays in either zoom mode
4800  {
4801  Display->ZoomOutFlag = false;
4803  }
4804  ClearandRebuildRailway(72); // if was zoomed out this displays the track because until ZoomOutFlag reset PlotOutput plots nothing
4805  TPoint MainScreenPoint(ScreenPosH + 8, ScreenPosV + 8); // new v2.2.0 add 8 to centre pointer in element
4806  TPoint CursPos = MainScreen->ClientToScreen(MainScreenPoint); // accurate funtion to convert from local to global co-ordinates
4807  Mouse->CursorPos = CursPos;
4808  Utilities->CallLogPop(2090);
4809  }
4810  catch(const Exception &e)
4811  {
4812  ErrorLog(200, e.Message);
4813  }
4814 }
4815 
4816 // ---------------------------------------------------------------------------
4817 
4819 {
4820  enum
4821  {
4822  PreStartTime, ActiveSegment, PostEnd} Segment;
4823  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",CompileAllEntriesMemoAndSetPointers");
4824  AllEntriesTTListBox->Clear();
4825  TEVPtr = 0;
4826  TTStartTimePtr = 0;
4827  TTFirstServicePtr = 0;
4828  TTLastServicePtr = 0; // all set to null to begin with
4829  if(TimetableEditVector.empty())
4830  {
4831  TTCurrentEntryPtr = 0;
4832  Utilities->CallLogPop(1681);
4833  return;
4834  }
4835  Segment = PreStartTime;
4836  for(TEVPtr = TimetableEditVector.begin(); TEVPtr != TimetableEditVector.end(); TEVPtr++)
4837  {
4838  if(Segment == PreStartTime) // looking for the start time
4839  {
4840  TDateTime TempTime; // dummy
4841  if(TrainController->CheckTimeValidity(33, *TEVPtr, TempTime))
4842  {
4843  TTStartTimePtr = TEVPtr; // TTStartTimeBox text set in TTHandler
4844  AllEntriesTTListBox->Items->Add("START " + (*TEVPtr).SubString(1, 5));
4845  Segment = ActiveSegment;
4846  continue;
4847  }
4848  else
4849  {
4850  if(*TEVPtr == "")
4851  {
4852  AllEntriesTTListBox->Items->Add("- Blank");
4853  }
4854  else
4855  {
4856  AnsiString CurrentStr = *TEVPtr;
4857  if(CurrentStr != "") // strip any non alphanumeric characters (specifically \r or \n)
4858  {
4859  CurrentStr = CurrentStr.SubString(1, 10); // limit length for LH window
4860  for(int x = 1; x < CurrentStr.Length(); x++)
4861  {
4862  if((CurrentStr[x] < 32) || (CurrentStr[1] > 126))
4863  {
4864  CurrentStr = CurrentStr.SubString(1, (x - 1));
4865  }
4866  }
4867  }
4868  AllEntriesTTListBox->Items->Add("- " + CurrentStr);
4869  }
4870  continue;
4871  }
4872  }
4873  if(Segment == ActiveSegment)
4874  {
4875  if(*TEVPtr != "")
4876  {
4877  if((*TEVPtr)[1] != '*')
4878  {
4880  ConvertCRLFsToCommas(0, *TEVPtr); // This needed because an entry intended as a service might have skipped the conversion in
4881  // SaveTTEntryButtonClick - see comment in that function
4882  if(TTFirstServicePtr == 0)
4883  {
4885  }
4887  }
4888  AnsiString Entry = *TEVPtr;
4889  if(Entry[1] == '*')
4890  Entry = "Comment";
4891  else
4892  {
4893  int SCPos = Entry.Pos(';'); // semicolon
4894  int CPos = Entry.Pos(','); // comma
4895  // 5 possibilities: no comma & no semicolon - just text - enter 1st 12 characters
4896  // both, comma before semicolon, i.e text on its own line, semicolon on next line - e.g. service headcode but no
4897  // description - enter the text up to the comma
4898  // both, semicolon before comma, normal - enter text up to the semicolon
4899  // comma & no semicolon, one or more lines of text without any semicolons - enter the text up to the comma
4900  // semicolon & no comma - enter text up to the semicolon
4901  if((CPos == 0) && (SCPos == 0))
4902  {
4903  Entry = Entry.SubString(1, 12);
4904  }
4905  else if((CPos > 0) && (SCPos > 0) && (CPos < SCPos))
4906  {
4907  Entry = Entry.SubString(1, CPos - 1);
4908  }
4909  else if((CPos > 0) && (SCPos > 0) && (CPos > SCPos))
4910  {
4911  Entry = Entry.SubString(1, SCPos - 1);
4912  }
4913  else if((CPos > 0) && (SCPos == 0))
4914  {
4915  Entry = Entry.SubString(1, CPos - 1);
4916  }
4917  else
4918  {
4919  Entry = Entry.SubString(1, SCPos - 1);
4920  }
4921  }
4922  AllEntriesTTListBox->Items->Add(Entry);
4923  continue;
4924  }
4925  else
4926  {
4927  Segment = PostEnd;
4928  AllEntriesTTListBox->Items->Add("END (Blank)");
4929  continue;
4930  }
4931  }
4932  if(Segment == PostEnd)
4933  {
4934  if(*TEVPtr == "")
4935  {
4936  AllEntriesTTListBox->Items->Add("+ Blank");
4937  }
4938  else
4939  {
4940  AnsiString CurrentStr = *TEVPtr;
4941  if(CurrentStr != "") // strip any non alphanumeric characters (specifically \r or \n)
4942  {
4943  CurrentStr = CurrentStr.SubString(1, 10);
4944  for(int x = 1; x < CurrentStr.Length(); x++)
4945  {
4946  if((CurrentStr[x] < 32) || (CurrentStr[1] > 126))
4947  {
4948  CurrentStr = CurrentStr.SubString(1, (x - 1));
4949  }
4950  }
4951  }
4952  AllEntriesTTListBox->Items->Add("+ " + CurrentStr);
4953  }
4954  continue;
4955  }
4956  }
4957  if(TTStartTimePtr == 0)
4958  {
4959  TTStartTimeBox->Text = "";
4960  }
4961  TTCurrentEntryPtr = TTLastServicePtr; // may well be reset outside this function but need to ensure that it has a valid value on exit, even if it's null
4962  Utilities->CallLogPop(1680);
4963 }
4964 // ---------------------------------------------------------------------------
4965 
4966 void __fastcall TInterface::AZOrderButtonClick(TObject *Sender)
4967 {
4968  try
4969  {
4970  if(TimetableEditVector.empty())
4971  {
4972  return; // should be able to access this if it is but keep in for safety
4973  }
4974  TrainController->LogEvent("AZOrderClick");
4975  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AZOrderClick");
4976  if(AZOrderButton->Caption == AnsiString("A-Z Order"))
4977  {
4978  TTEVPtr SortStart, SortEnd;
4979  UnicodeString MessageStr =
4980  "If you wish to preserve the original order don't make any changes whilst in alphabetical order.\n\nIn that case use alphabetical order to find the service required, click it to display it, then revert to the original order where the same service will be displayed and can be changed.";
4981  Application->MessageBox(MessageStr.c_str(), L"Please Note:", MB_OK | MB_ICONWARNING);
4984  SortStart = TimetableEditVector.begin(); // if no start time set sort from beginning
4985  if(TTFirstServicePtr != NULL)
4986  {
4987  SortStart = TTFirstServicePtr;
4988  }
4989  SortEnd = TimetableEditVector.end(); // if no last service set sort to end
4990  if(TTLastServicePtr != NULL)
4991  {
4992  SortEnd = TTLastServicePtr + 1;
4993  }
4994  std::sort(SortStart, SortEnd);
4996  bool CurrentEntryChanged = false;
4997  for(TTimetableEditVector::iterator x = TimetableEditVector.begin(); x < TimetableEditVector.end(); x++)
4998  {
4999  if(TTSelectedEntry == *x)
5000  {
5001  TTCurrentEntryPtr = x;
5002  CurrentEntryChanged = true;
5003  }
5004  }
5005  if(!CurrentEntryChanged)
5006  {
5008  }
5009  AZOrderButton->Caption = AnsiString("Original Order");
5010  AZOrderButton->Hint = AnsiString("Arrange services in original order Toggle with Shift+ Z");
5011  }
5012  else
5013  {
5015  {
5016  UnicodeString MessageStr =
5017  "Reverting to the original order will discard any changes made whilst in alphabetical order.\n\nTo preserve the changes click 'No', then save the timetable or use 'save as' if you wish to keep the original timetable.\n\nDo you wish to proceed?";
5018  int button = Application->MessageBox(MessageStr.c_str(), L"Warning!", MB_YESNO | MB_ICONWARNING);
5019  if(button == IDNO)
5020  {
5021  TimetableChangedFlag = true;
5022  TimetableValidFlag = false;
5024  SetLevel1Mode(135);
5025  Utilities->CallLogPop(2166);
5026  return;
5027  }
5028  }
5032  bool CurrentEntryChanged = false;
5033  for(TTimetableEditVector::iterator x = TimetableEditVector.begin(); x < TimetableEditVector.end(); x++)
5034  {
5035  if(TTSelectedEntry == *x)
5036  {
5037  TTCurrentEntryPtr = x;
5038  CurrentEntryChanged = true;
5039  }
5040  }
5041  if(!CurrentEntryChanged)
5042  {
5044  }
5045  AZOrderButton->Caption = AnsiString("A-Z Order");
5046  AZOrderButton->Hint = AnsiString("Arrange services in alphabetical order Toggle with Shift+ Z");
5047  }
5048  TimetableChangedFlag = true;
5049  TimetableValidFlag = false;
5052  SetLevel1Mode(136);
5053  Utilities->CallLogPop(2165);
5054  }
5055  catch(const Exception &e)
5056  {
5057  ErrorLog(211, e.Message);
5058  }
5059 }
5060 
5061 // ---------------------------------------------------------------------------
5062 
5063 void TInterface::ConvertCRLFsToCommas(int Caller, AnsiString &ConvStr)
5064 {
5065  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ConvertCRLFsToCommas," + ConvStr);
5066  AnsiString OutStr = "";
5067  int x = 1; // AnsiString arrays start at 1
5068 
5069  while(x < ConvStr.Length()) // skip the last character as looking for CRLF pairs, i.e. '\r' followed by '\n'
5070  {
5071  if((ConvStr[x] == '\r') && (ConvStr[x + 1] == '\n'))
5072  {
5073  OutStr += ',';
5074  x++;
5075  x++;
5076  }
5077  else
5078  {
5079  OutStr += ConvStr[x];
5080  x++;
5081  }
5082  }
5083  if(x == ConvStr.Length())
5084  OutStr += ConvStr[x]; // add the last character
5085 
5086 // strip any excess commas from the end
5087  if(OutStr != "")
5088  {
5089  while(OutStr[OutStr.Length()] == ',')
5090  {
5091  OutStr = OutStr.SubString(1, OutStr.Length() - 1);
5092  if(OutStr == "")
5093  break; // if consisted of just commas then without this would fail on range error when becomes a null string
5094  }
5095  }
5096  ConvStr = OutStr;
5097  if(ConvStr == "")
5098  ConvStr = ','; // don't return a null or will fail, OK to return a comma on its own as will be ignored during ProcessOneTimetableLine
5099  // when AllCommas will be true
5100  Utilities->CallLogPop(1846);
5101 }
5102 
5103 // ---------------------------------------------------------------------------
5104 
5106 {
5107 /* CreateEditTTFileName set if a TT file loaded (even if empty), the pointers TTStartTimePtr, TTFirstServicePtr, TTLastServicePtr provide
5108  relevant information - if null then not set. TTCurrentEntryPtr is set to the Entry to be displayed or null if there's no start time or no
5109  entries
5110 */
5111  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TimetableHandler");
5112  PreviousTTEntryButton->Enabled = false;
5113  NextTTEntryButton->Enabled = false;
5114  AddMinsButton->Enabled = false;
5115  SubMinsButton->Enabled = false;
5116  CopyTTEntryButton->Enabled = false;
5117  CutTTEntryButton->Enabled = false;
5118  PasteTTEntryButton->Enabled = false;
5119  DeleteTTEntryButton->Enabled = false;
5120  SaveTTEntryButton->Enabled = false;
5121  SaveTTButton->Enabled = false;
5122  SaveTTAsButton->Enabled = false;
5123  ValidateTimetableButton->Enabled = false;
5124  AZOrderButton->Enabled = false;
5125  TTServiceSyntaxCheckButton->Enabled = false;
5126  NewTTEntryButton->Enabled = false;
5127  MoveTTEntryUpButton->Enabled = false;
5128  MoveTTEntryDownButton->Enabled = false;
5129  CancelTTEntryButton->Enabled = false;
5130  RestoreTTButton->Enabled = false;
5131  ExportTTButton->Enabled = false;
5132  ConflictAnalysisButton->Enabled = false;
5133  ExitTTModeButton->Enabled = true;
5134 
5136  {
5137  AZOrderButton->Enabled = true;
5138  }
5139 
5141  TimetableValidFlag = false; // should always be the case anyway but include here to be sure
5142 
5143  if(CreateEditTTFileName == "")
5144  {
5145  TimetableNameLabel->Caption = "Creating new timetable: not yet saved";
5146  }
5147  else
5148  {
5149  TimetableNameLabel->Caption = "Editing timetable: " + CreateEditTTTitle;
5150  }
5151 
5152  if(TTStartTimePtr != 0) // Null means start time not yet set
5153  {
5154  TTStartTimeBox->Text = (*TTStartTimePtr).SubString(1, 5); // 1st 5 chars = time if validity check OK
5155  }
5156 // start time now set & displayed
5157 
5159  {
5160  InfoPanel->Visible = true;
5161  InfoPanel->Caption = "Select option or change entry";
5162  if(RailwayTitle != "")
5163  {
5164  ShowHideTTButton->Enabled = true;
5165  }
5166  else
5167  {
5168  ShowHideTTButton->Enabled = false;
5169  }
5170  ExitTTModeButton->Enabled = true;
5171  AllEntriesTTListBox->Enabled = true;
5172  AnsiString AnsiAddSubText(AddSubMinsBox->Text);
5173  if((AnsiAddSubText != "") && AreAnyTimesInCurrentEntry())
5174  {
5175  bool ValidFlag = true;
5176  for(int x = 1; x <= AnsiAddSubText.Length(); x++)
5177  {
5178  if((AnsiAddSubText[x] > '9') || (AnsiAddSubText[x] < '0'))
5179  {
5180  ValidFlag = false;
5181  break;
5182  }
5183  }
5184  if(ValidFlag)
5185  {
5186  if(AnsiAddSubText.ToInt() != 0)
5187  {
5188  AddMinsButton->Enabled = true;
5189  SubMinsButton->Enabled = true;
5190  }
5191  }
5192  }
5194  {
5195  RestoreTTButton->Enabled = true;
5196  }
5198  { // Need !TimetableChangedFlag because the changed TT must be saved before validation - it's the TT file that is checked
5199  // so if it is changed but not saved, the 'correct' file will check OK but the changed TT may well not be valid
5200  ValidateTimetableButton->Enabled = true;
5201  }
5203  {
5204  ExportTTButton->Enabled = true;
5205  ConflictAnalysisButton->Enabled = true;
5206  }
5207  if(TTCurrentEntryPtr != 0)
5208  {
5209  CopyTTEntryButton->Enabled = true;
5210  CutTTEntryButton->Enabled = true;
5211  DeleteTTEntryButton->Enabled = true;
5212  }
5213  if((TimetableChangedFlag) && !TimetableEditVector.empty())
5214  {
5215  SaveTTButton->Enabled = true;
5216  }
5217  if(!TimetableEditVector.empty())
5218  {
5219  SaveTTAsButton->Enabled = true;
5220  }
5222  {
5223  NewTTEntryButton->Enabled = true;
5224  }
5225  if((TTCurrentEntryPtr > 0) && !TimetableEditVector.empty())
5226  {
5227  if((TimetableEditVector.end() - 1) > TTCurrentEntryPtr)
5228  {
5229  NextTTEntryButton->Enabled = true;
5230  MoveTTEntryDownButton->Enabled = true;
5231  }
5233  {
5234  PreviousTTEntryButton->Enabled = true;
5235  MoveTTEntryUpButton->Enabled = true;
5236  }
5237  }
5238  if(TTCurrentEntryPtr > 0)
5239  {
5240  if(*TTCurrentEntryPtr != "")
5241  {
5243  {
5244  TTServiceSyntaxCheckButton->Enabled = true;
5245  }
5246  }
5247  }
5248  if(CopiedEntryFlag)
5249  {
5250  PasteTTEntryButton->Enabled = true;
5251  }
5252  OneEntryTimetableMemo->Clear(); // don't clear if Entry changed
5253  if(TTCurrentEntryPtr > 0)
5254  {
5255 // if(*TTCurrentEntryPtr != "") leave this out or fails to highlight blank line entries
5257  {
5258  bool ServiceEntry = true;
5259  DisplayOneTTLineInPanel(0, *TTCurrentEntryPtr, ServiceEntry);
5260  }
5261  else
5262  {
5263  bool ServiceEntry = false;
5264  DisplayOneTTLineInPanel(1, *TTCurrentEntryPtr, ServiceEntry);
5265  }
5266  }
5267  }
5268  else
5269  {
5270  CancelTTEntryButton->Enabled = true;
5271  SaveTTEntryButton->Enabled = true;
5272  ShowHideTTButton->Enabled = false;
5273  ExitTTModeButton->Enabled = false;
5274  AllEntriesTTListBox->Enabled = false; // to stop entries being selected
5275  InfoPanel->Caption = "Add or change entry then save it, or cancel";
5276  InfoPanel->Visible = true;
5277  }
5278  Utilities->CallLogPop(1600);
5279 }
5280 
5281 // ---------------------------------------------------------------------------
5282 void TInterface::DisplayOneTTLineInPanel(int Caller, AnsiString Data, bool ServiceEntry)
5283 {
5284  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",DisplayOneTTLineInPanel," + Data + ", " +
5285  AnsiString((short)ServiceEntry));
5286  OneEntryTimetableMemo->Clear();
5287  if(ServiceEntry)
5288  {
5289  TrainController->StripSpaces(1, Data);
5290  while(true)
5291  {
5292  int CommaPos = Data.Pos(',');
5293  if((CommaPos == 0) && (Data != ""))
5294  {
5295  CommaPos = Data.Length() + 1;
5296  }
5297  OneEntryTimetableMemo->Lines->Add(Data.SubString(1, CommaPos - 1));
5298  if(Data.Length() <= CommaPos)
5299  break;
5300  Data = Data.SubString(CommaPos + 1, Data.Length() - CommaPos);
5301  }
5302  }
5303  else
5304  {
5305  OneEntryTimetableMemo->Text = Data;
5306  }
5307  int TotalLines = OneEntryTimetableMemo->Lines->Count; // remove excess lines at bottom
5308 
5309  while((OneEntryTimetableMemo->Lines->Strings[TotalLines - 1] == "") || (OneEntryTimetableMemo->Lines->Strings[TotalLines - 1] == "\r\n"))
5310  {
5311  OneEntryTimetableMemo->Lines->Delete(TotalLines - 1);
5312  TotalLines--;
5313  if(TotalLines < 1)
5314  break;
5315  }
5316  OneEntryTimetableMemo->HideSelection = true;
5317  OneEntryTimetableMemo->SelStart = 0; // need this & next command to set cursor to the top
5318  OneEntryTimetableMemo->SelLength = 0;
5320  Utilities->CallLogPop(1602);
5321 }
5322 // ---------------------------------------------------------------------------
5323 
5325 {
5326  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",HighlightOneEntryInAllEntriesTTListBox," + AnsiString(Position));
5327  if(TimetableEditVector.empty() || (AllEntriesTTListBox->Items->Count == 0))
5328  {
5329  HighlightPanel->Top = 32;
5330  HighlightPanel->Caption = "";
5331  HighlightPanel->Width = 100;
5332  HighlightPanel->Visible = false;
5333  }
5334  else
5335  {
5336  AnsiString CurrentStr = AllEntriesTTListBox->Items->Strings[Position];
5337  if(CurrentStr != "") // strip any non alphanumeric characters (specifically \r or \n)
5338  {
5339  for(int x = 1; x < CurrentStr.Length(); x++)
5340  {
5341  if((CurrentStr[x] < 32) || (CurrentStr[1] > 126))
5342  {
5343  CurrentStr = CurrentStr.SubString(1, (x - 1));
5344  }
5345  }
5346  }
5347  HighlightPanel->Top = 32 + (Position * 13) - (AllEntriesTTListBox->TopIndex * 13);
5348  if(HighlightPanel->Top < 32)
5349  HighlightPanel->Visible = false;
5350  else
5351  HighlightPanel->Visible = true; // doesn't matter if goes off the bottom as it becomes invisible as then it's off its parent panel
5352  HighlightPanel->Caption = CurrentStr;
5353  if(AllEntriesTTListBox->Items->Count > 47) //because the scrollbar will be present
5354  HighlightPanel->Width = 82;
5355  else
5356  HighlightPanel->Width = 100;
5357  }
5358  Utilities->CallLogPop(1709);
5359 }
5360 
5361 // ---------------------------------------------------------------------------
5363 {
5364  if((TTCurrentEntryPtr == 0) || (*TTCurrentEntryPtr == ""))
5365  {
5366  return false;
5367  }
5368  TDateTime DummyTime;
5369  bool TimesPresent = false;
5370 
5371  for(int x = 0; x < OneEntryTimetableMemo->Lines->Count; x++)
5372  {
5373  for(int y = 1; y < (OneEntryTimetableMemo->Lines->Strings[x].Length() - 3); y++)
5374  {
5375  if(TrainController->CheckTimeValidity(20, OneEntryTimetableMemo->Lines->Strings[x].SubString(y, 5), DummyTime))
5376  {
5377  TimesPresent = true;
5378  break;
5379  }
5380  }
5381  if(TimesPresent)
5382  break;
5383  }
5384  return TimesPresent;
5385 }
5386 
5387 // ---------------------------------------------------------------------------
5388 // end of Timetable editing functions
5389 // ---------------------------------------------------------------------------
5390 void __fastcall TInterface::ExitMenuItemClick(TObject *Sender)
5391 {
5392  try
5393  {
5394  TrainController->LogEvent("ExitMenuItemClick");
5395  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ExitMenuItemClick");
5397  {
5398  UnicodeString MessageStr =
5399  "Note that leaving the track unlinked will cause preferred directions to be lost on reloading. Prevent by linking the track then resaving. Do you still wish to exit?";
5400  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
5401  if(button == IDNO)
5402  {
5403  Utilities->CallLogPop(1711);
5404  return;
5405  }
5406  }
5407  if(FileChangedFlag)
5408  {
5409  UnicodeString MessageStr = "The railway has changed, exit without saving?";
5410  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
5411  if(button == IDNO)
5412  {
5413  Utilities->CallLogPop(1180);
5414  return;
5415  }
5416  }
5417  if((TempTTFileName != "") && FileExists(TempTTFileName))
5418  {
5419  DeleteFile(TempTTFileName);
5420  }
5421  Utilities->CallLogPop(1181);
5422  Application->Terminate();
5423  }
5424  catch(const Exception &e)
5425  {
5426  ErrorLog(140, e.Message);
5427  }
5428 }
5429 // ---------------------------------------------------------------------------
5430 
5431 void __fastcall TInterface::TrackInfoOnOffMenuItemClick(TObject *Sender)
5432 {
5433  try
5434  {
5435  TrainController->LogEvent("TrackInfoOnOffMenuItemClick");
5436  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TrackInfoOnOffMenuItemClick");
5437  if(TrackInfoOnOffMenuItem->Caption == "Show")
5438  {
5439  TrackInfoOnOffMenuItem->Caption = "Hide";
5440  }
5441  else
5442  {
5443  TrackInfoOnOffMenuItem->Caption = "Show";
5444  }
5445  Utilities->CallLogPop(1183);
5446  }
5447  catch(const Exception &e)
5448  {
5449  ErrorLog(173, e.Message);
5450  }
5451 }
5452 // ---------------------------------------------------------------------------
5453 
5454 void __fastcall TInterface::TrainStatusInfoOnOffMenuItemClick(TObject *Sender)
5455 {
5456  try
5457  {
5458  TrainController->LogEvent("TrainStatusInfoOnOffMenuItemClick");
5459  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TrainStatusInfoOnOffMenuItemClick");
5460  if(TrainStatusInfoOnOffMenuItem->Caption == "Show Status")
5461  {
5462  TrainStatusInfoOnOffMenuItem->Caption = "Hide Status";
5463  }
5464  else
5465  {
5466  TrainStatusInfoOnOffMenuItem->Caption = "Show Status";
5467  }
5468  Utilities->CallLogPop(1184);
5469  }
5470  catch(const Exception &e)
5471  {
5472  ErrorLog(141, e.Message);
5473  }
5474 }
5475 
5476 // ---------------------------------------------------------------------------
5477 void __fastcall TInterface::TrainTTInfoOnOffMenuItemClick(TObject *Sender)
5478 {
5479  try
5480  {
5481  TrainController->LogEvent("TrainTTInfoOnOffMenuItemClick");
5482  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TrainTTInfoOnOffMenuItemClick");
5483  if(TrainTTInfoOnOffMenuItem->Caption == "Show Timetable")
5484  {
5485  TrainTTInfoOnOffMenuItem->Caption = "Hide Timetable";
5486  }
5487  else
5488  {
5489  TrainTTInfoOnOffMenuItem->Caption = "Show Timetable";
5490  }
5491  Utilities->CallLogPop(1185);
5492  }
5493  catch(const Exception &e)
5494  {
5495  ErrorLog(142, e.Message);
5496  }
5497 }
5498 
5499 // ---------------------------------------------------------------------------
5500 // Dragging Functions
5501 // ---------------------------------------------------------------------------
5502 void __fastcall TInterface::AcceptDragging(TObject *Sender, TObject *Source, int X, int Y, TDragState State, bool &Accept)
5503 {
5504 // allow in zoom out mode
5505  try
5506  {
5507 // TrainController->LogEvent("AcceptDragging"); drop this, have too many
5508  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",AcceptDragging");
5509  if((Source == PerformancePanel) || (Source == PerformancePanelLabel) || (Source == PerformanceLogBox))
5510  {
5511  Accept = true;
5512  int PPLeft = PerformancePanel->Left;
5513  int PPTop = PerformancePanel->Left;
5514 
5515  PPLeft = Mouse->CursorPos.x - PerformancePanelDragStartX;
5516  PPTop = Mouse->CursorPos.y - PerformancePanelDragStartY;
5517  if((PPLeft + PerformancePanel->Width) < 32)
5518  PPLeft = 32 - PerformancePanel->Width;
5519  if(PPLeft > (MainScreen->Left + MainScreen->Width))
5520  PPLeft = MainScreen->Left + MainScreen->Width;
5521  if((PPTop + PerformancePanel->Height) < MainScreen->Top)
5522  PPTop = MainScreen->Top - PerformancePanel->Height;
5523  if(PPTop > (MainScreen->Top + MainScreen->Height - 20))
5524  PPTop = MainScreen->Top + MainScreen->Height - 20;
5525  PerformancePanel->Left = PPLeft;
5526  PerformancePanel->Top = PPTop;
5527  }
5528  else if((Source == OperatorActionPanel) || (Source == OAPanelLabel))
5529  // not the listbox because that used for selecting trains
5530  {
5531  Accept = true;
5532  int OALeft = OperatorActionPanel->Left;
5533  int OATop = OperatorActionPanel->Left;
5534 
5535  OALeft = Mouse->CursorPos.x - OperatorActionPanelDragStartX;
5536  OATop = Mouse->CursorPos.y - OperatorActionPanelDragStartY;
5537  if((OALeft + OperatorActionPanel->Width) < 32)
5538  OALeft = 32 - OperatorActionPanel->Width;
5539  if(OALeft > (MainScreen->Left + MainScreen->Width))
5540  OALeft = MainScreen->Left + MainScreen->Width;
5541  if((OATop + OperatorActionPanel->Height) < MainScreen->Top)
5542  OATop = MainScreen->Top - OperatorActionPanel->Height;
5543  if(OATop > (MainScreen->Top + MainScreen->Height - 20))
5544  OATop = MainScreen->Top + MainScreen->Height - 20;
5545  OperatorActionPanel->Left = OALeft;
5546  OperatorActionPanel->Top = OATop;
5547  }
5548  else
5549  Accept = false;
5550  Utilities->CallLogPop(1186);
5551  }
5552  catch(const Exception &e)
5553  {
5554  ErrorLog(143, e.Message);
5555  }
5556 }
5557 
5558 // ---------------------------------------------------------------------------
5559 void __fastcall TInterface::PerformancePanelStartDrag(TObject *Sender, TDragObject *&DragObject)
5560 {
5561 // allow in zoom out mode
5562  try
5563  {
5564  TrainController->LogEvent("PerformancePanelStartDrag");
5565  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PerformancePanelStartDrag");
5566  PerformancePanelDragStartX = Mouse->CursorPos.x - PerformancePanel->Left;
5567  PerformancePanelDragStartY = Mouse->CursorPos.y - PerformancePanel->Top;
5568  Utilities->CallLogPop(1187);
5569  }
5570  catch(const Exception &e)
5571  {
5572  ErrorLog(144, e.Message);
5573  }
5574 }
5575 // ---------------------------------------------------------------------------
5576 
5577 void __fastcall TInterface::OperatorActionPanelStartDrag(TObject *Sender, TDragObject *&DragObject) // new v2.2.0
5578 
5579 {
5580 // allow in zoom out mode
5581  try
5582  {
5583  TrainController->LogEvent("OperatorActionPanelStartDrag");
5584  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OperatorActionPanelStartDrag");
5585  OperatorActionPanelDragStartX = Mouse->CursorPos.x - OperatorActionPanel->Left;
5586  OperatorActionPanelDragStartY = Mouse->CursorPos.y - OperatorActionPanel->Top;
5587  Utilities->CallLogPop(2091);
5588  }
5589  catch(const Exception &e)
5590  {
5591  ErrorLog(201, e.Message);
5592  }
5593 }
5594 
5595 // ---------------------------------------------------------------------------
5596 // Mouse Functions
5597 // ---------------------------------------------------------------------------
5598 void __fastcall TInterface::MainScreenMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
5599  // caller function - stops master clock
5600 {
5601 // have to allow in zoom out mode
5602  try
5603  {
5604  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MainScreenMouseDown," + AnsiString(Button) + "," + AnsiString(X) + "," + AnsiString(Y));
5605  bool ClockState = Utilities->Clock2Stopped;
5606  Utilities->Clock2Stopped = true;
5607 
5608  RestoreFocusPanel->Enabled = true; // these added at v2.0.0 to restore navigation keys to move screen when a panel had focus
5609  RestoreFocusPanel->Visible = true; // because then these buttons just cycled through the panel buttons. Added in place of the
5610  RestoreFocusPanel->SetFocus(); // section in ClockTimer2 where focus restored every clock cycle, because then the help screen
5611  RestoreFocusPanel->Visible = false; // was hidden. At least now help is only hidden when the screen clicked, which is normal
5612  RestoreFocusPanel->Enabled = false; // behaviour, and can tell user that can restore navigation keys just by clicking the screen
5613 
5615  {
5616  if(!Display->ZoomOutFlag)
5617  MainScreenMouseDown2(0, Button, Shift, X, Y);
5618  else
5619  MainScreenMouseDown3(0, Button, Shift, X, Y);
5620  }
5621  Utilities->Clock2Stopped = ClockState;
5622  Utilities->CallLogPop(33);
5623  }
5624  catch(const Exception &e)
5625  {
5626  ErrorLog(19, e.Message);
5627  }
5628 }
5629 
5630 // ---------------------------------------------------------------------------
5631 void TInterface::MainScreenMouseDown2(int Caller, TMouseButton Button, TShiftState Shift, int X, int Y)
5632 {
5633  try
5634  {
5635  TrainController->LogEvent("MainScreenMouseDown2," + AnsiString(Button) + "," + AnsiString(X) + "," + AnsiString(Y));
5636  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",MainScreenMouseDown2," + AnsiString(Button) + "," + AnsiString(X) +
5637  "," + AnsiString(Y));
5638  // unplot GapFlash graphics if plotted & cancel gap flashing if left mouse button pressed (so can move display with right mouse button)
5639  // but not in ZoomOut mode - so can switch between modes & keep gaps flashing
5640  if(Track->GapFlashFlag && !Display->ZoomOutFlag && (Button == mbLeft))
5641  {
5644  Track->GapFlashFlag = false;
5645  }
5646  int HLoc, VLoc;
5647  Track->GetTrackLocsFromScreenPos(1, HLoc, VLoc, X, Y);
5648  int NoOffsetX, NoOffsetY;
5649  Track->GetTruePositionsFromScreenPos(0, NoOffsetX, NoOffsetY, X, Y);
5650  if(Button == mbRight) // track, PrefDir or text erase, PrefDir/route truncate, or take signaller control of train
5651  {
5652  // this routine new at v2.1.0. Allows railway moving for zoom-in mode when no element at HLoc & VLoc
5653  int Dummy; // unused in next function
5654  AnsiString Text = ""; //needed for TextFound but not used
5655  if(!Track->TrackElementPresentAtHV(0, HLoc, VLoc) && !Track->InactiveTrackElementPresentAtHV(0, HLoc, VLoc) && !Track->UserGraphicPresentAtHV(0, X, Y, Dummy) &&
5656  !TextHandler->TextFound(0, X + (Display->DisplayOffsetH * 16), Y + (Display->DisplayOffsetV * 16), Text))
5657  {
5660  WholeRailwayMoving = true;
5661  Screen->Cursor = TCursor(-22); // Four arrows;
5662  }
5663 
5664  else if(Level2TrackMode == AddText)
5665  {
5666  TrainController->LogEvent("mbRight + AddText");
5668  if(TextHandler->TextFound(1, NoOffsetX, NoOffsetY, Text))
5669  {
5670  if(TextHandler->TextErase(0, NoOffsetX, NoOffsetY, Text)) // erase text in vector
5671  {
5673  if(NoRailway())
5674  {
5675  EditMenu->Enabled = false;
5676  }
5677  else
5678  EditMenu->Enabled = true;
5679  }
5680  }
5681  SetLevel2TrackMode(57); // to remove 'move text' if last text item removed
5682  Utilities->CallLogPop(34);
5683  return;
5684  }
5685  else if(Level2TrackMode == AddGraphic)
5686  {
5687  TrainController->LogEvent("mbRight + AddGraphic");
5688  if(Track->UserGraphicVector.empty()) // no user graphics
5689  {
5690  Utilities->CallLogPop(2180);
5691  return;
5692  }
5693  int UGIVecPos;
5694  if(Track->UserGraphicPresentAtHV(1, X, Y, UGIVecPos))
5695  {
5696  Track->UserGraphicVector.erase(Track->UserGraphicVector.begin() + UGIVecPos);
5698  if(NoRailway())
5699  {
5700  EditMenu->Enabled = false;
5701  }
5702  else
5703  EditMenu->Enabled = true;
5704  }
5705  Utilities->CallLogPop(2181);
5706  return;
5707  }
5708 
5709  else if(Level2TrackMode == AddTrack)
5710  {
5711  TrainController->LogEvent("mbRight + AddTrack");
5712  bool TrackEraseSuccessfulFlag;
5713  int ErasedTrackVectorPosition;
5714  Screen->Cursor = TCursor(-11); // Hourglass;
5715  Track->EraseTrackElement(1, HLoc, VLoc, ErasedTrackVectorPosition, TrackEraseSuccessfulFlag, true);
5716  if(TrackEraseSuccessfulFlag)
5717  {
5718  if(ErasedTrackVectorPosition > -1)
5719  EveryPrefDir->RealignAfterTrackErase(0, ErasedTrackVectorPosition);
5722  ClearandRebuildRailway(5); // to ensure location named elements plotted correctly & replot the grid if required
5723  SetGapsButton->Enabled = false; // if conditions have changed need to reset buttons, best not calling SetLevel2TrackMode as that
5724  TrackOKButton->Enabled = false; // calls Clearand.. if gridflag set & takes a long time
5725  if(Track->GapsUnset(1))
5726  {
5727  SetGapsButton->Enabled = true;
5728  }
5729  // only enable if there are gaps still to be set (returns false for no track)
5730  else
5731  {
5732  if(!(Track->NoActiveTrack(0)) && !(Track->IsTrackFinished()))
5733  {
5734  TrackOKButton->Enabled = true;
5735  }
5736  // TrackOK only enabled if track exists, there are no unset gaps, and track not finished
5737  }
5738  if(!(Track->IsTrackFinished())) // can only set lengths for several elements together if TrackFinished
5739  {
5740  SetLengthsButton->Enabled = false;
5741  }
5742 // if(NoRailway()) dropped at v2.6.0 to allow edits during AddTrack
5743 // {
5744 // EditMenu->Enabled = false;
5745 // }
5746 // else
5747  EditMenu->Enabled = true;
5748  }
5749  Screen->Cursor = TCursor(-2); // Arrow
5750  Utilities->CallLogPop(35);
5751  return;
5752  }
5753  else if(Level2TrackMode == DistanceContinuing) // new for extended distances (similar to PrefDirContinuing)
5754  {
5755  TrainController->LogEvent("mbRight + DistanceContinuing");
5757  bool LeadingPointsAtLastElement = false;
5758  if(ConstructPrefDir->GetPrefDirTruncateElement(0, HLoc, VLoc))
5759  {
5760  if(ConstructPrefDir->PrefDirSize() == 0)
5761  {
5763  SetLevel1Mode(64);
5765  SetLevel2TrackMode(51); // calls ClearandRebuildRailway to show length erased & sets back to start
5766  Utilities->CallLogPop(1526);
5767  return;
5768  }
5771  ConstructPrefDir->CalcDistanceAndSpeed(0, OverallDistance, OverallSpeedLimit, LeadingPointsAtLastElement);
5772  if(!LeadingPointsAtLastElement)
5773  {
5774  TrackLengthPanel->Visible = true;
5775  TrackLengthPanel->SetFocus();
5776  InfoPanel->Visible = true;
5777  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Continue or set values (overall length), or right click to cancel/truncate";
5778  RestoreAllDefaultLengthsButton->Enabled = true;
5779  ResetDefaultLengthButton->Enabled = true;
5780  LengthOKButton->Enabled = true;
5781  DistanceBox->Text = AnsiString(OverallDistance);
5782  if(OverallSpeedLimit > -1)
5783  SpeedLimitBox->Text = AnsiString(OverallSpeedLimit);
5784  else
5785  SpeedLimitBox->Text = "Mixed";
5786  }
5787  else
5788  {
5789  TrackLengthPanel->Visible = true;
5790  TrackLengthPanel->SetFocus();
5791  InfoPanel->Visible = true;
5792  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Can't end on leading points, continue or truncate";
5793  RestoreAllDefaultLengthsButton->Enabled = false;
5794  ResetDefaultLengthButton->Enabled = false;
5795  LengthOKButton->Enabled = false;
5796  }
5798  }
5799  Utilities->CallLogPop(36);
5800  return;
5801  }
5802 
5803  else if(Level2PrefDirMode == PrefDirContinuing) // truncate
5804  {
5805  TrainController->LogEvent("mbRight + PrefDirContinuing");
5807 // RlyFile = false; - don't alter this just for PrefDir changes
5808  if(ConstructPrefDir->GetPrefDirTruncateElement(1, HLoc, VLoc))
5809  {
5810  if(ConstructPrefDir->PrefDirSize() == 0)
5811  {
5813  SetLevel1Mode(14); // all PrefDir truncated
5814  Utilities->CallLogPop(37);
5815  return;
5816  }
5818  }
5820  SetLevel2PrefDirMode(0); // calls ClearandRebuildRailway to show length erased & sets back to start
5821  Utilities->CallLogPop(38);
5822  return;
5823  }
5824 
5825  else if((Level1Mode == PrefDirMode) && (Level2PrefDirMode != PrefDirContinuing) && (Level2PrefDirMode != PrefDirSelecting)) // delete element
5826  {
5827  TrainController->LogEvent("mbRight + != PrefDirContinuing");
5829 // RlyFile = false; - don't alter this just for PrefDir changes
5832  SetLevel1Mode(15); // calls ClearandRebuildRailway to show length erased & sets back to start
5833  Utilities->CallLogPop(39);
5834  return;
5835  }
5836 
5837  else if((Level2OperMode == Operating) || (Level2OperMode == PreStart)) // disallow when paused, but allow some parts in prestart
5838  {
5839  TrainController->LogEvent("mbRight + OperMode");
5840  bool FoundFlag;
5841  int VecPos = Track->GetVectorPositionFromTrackMap(1, HLoc, VLoc, FoundFlag);
5842  if(FoundFlag && (Level2OperMode != PreStart)) // disallow signaller control in PreStart
5843  {
5845  // signaller control of train
5846  if(SelectedTrainID > -1)
5847  {
5850  if((Train.LeadElement == -1) || (Track->TrackElementAt(788, Train.LeadElement).Conn[Train.LeadExitPos] == -1))
5851  {
5852  if(Train.TrainMode == Signaller)
5853  {
5855  }
5856  }
5857  if((Train.Stopped()) || (Train.TrainFailed && !(Train.TrainMode == Signaller)) ||
5859  !Train.StepForwardFlag))
5860  // don't allow signaller popup menu in timetable mode unless stopped,
5861  // or when coming to a stop or leaving at a continuation when under signaller control
5862  // or when failed
5863  {
5864  // don't allow selection if another stopped train at a bridge position
5865  if(Track->TrackElementAt(630, VecPos).TrackType == Bridge)
5866  {
5867  int TrainID01 = Track->TrackElementAt(631, VecPos).TrainIDOnBridgeTrackPos01;
5868  int TrainID23 = Track->TrackElementAt(632, VecPos).TrainIDOnBridgeTrackPos23;
5869  if((TrainID01 > -1) && (TrainID23 > -1))
5870  {
5871  TrainController->StopTTClockMessage(0, "Can't select a train at a bridge when another train is at the same bridge");
5872  Utilities->CallLogPop(1103);
5873  return;
5874  }
5875  }
5876  if(Train.TrainMode == Timetable)
5877  {
5878  TakeSignallerControlMenuItem->Enabled = true;
5879  TimetableControlMenuItem->Enabled = false;
5880  ChangeDirectionMenuItem->Enabled = false;
5881  MoveForwardsMenuItem->Enabled = false;
5882  SignallerJoinedByMenuItem->Enabled = false;
5883  RepairFailedTrainMenuItem->Enabled = false;
5884  StepForwardMenuItem->Enabled = false;
5885  RemoveTrainMenuItem->Enabled = false;
5886  PassRedSignalMenuItem->Enabled = false;
5887  SignallerControlStopMenuItem->Enabled = false;
5888  }
5889  else // signaller mode
5890  {
5891  TakeSignallerControlMenuItem->Enabled = false;
5892  if((Train.Crashed) || (Train.Derailed))
5893  {
5894  TimetableControlMenuItem->Enabled = false;
5895  ChangeDirectionMenuItem->Enabled = false;
5896  MoveForwardsMenuItem->Enabled = false;
5897  SignallerJoinedByMenuItem->Enabled = false;
5898  RepairFailedTrainMenuItem->Enabled = false;
5899  StepForwardMenuItem->Enabled = false;
5900  PassRedSignalMenuItem->Enabled = false;
5901  SignallerControlStopMenuItem->Enabled = false;
5902  RemoveTrainMenuItem->Enabled = true;
5903  }
5904  else if(Train.Stopped())
5905  {
5906  if(Train.TimetableFinished)
5907  {
5908  TimetableControlMenuItem->Enabled = false;
5909  }
5910  else
5911  {
5912  if(Train.RestoreTimetableLocation == "") // en route
5913  {
5914  TimetableControlMenuItem->Enabled = true;
5915  }
5916  else
5917  {
5918  // obtain train location & check if OK for restoration of tt control
5919  AnsiString LocName = "";
5920  if(Train.LeadElement > -1)
5921  {
5922  LocName = Track->TrackElementAt(802, Train.LeadElement).ActiveTrackElementName;
5923  }
5924  if((LocName == "") && (Train.MidElement > -1))
5925  {
5926  LocName = Track->TrackElementAt(803, Train.MidElement).ActiveTrackElementName;
5927  }
5928  if(Train.RestoreTimetableLocation == LocName)
5929  {
5930  TimetableControlMenuItem->Enabled = true;
5931  }
5932  else
5933  {
5934  TimetableControlMenuItem->Enabled = false;
5935  }
5936  }
5937  }
5938 // don't allow ChangeDirection if lead or mid elements (but not lag or next) -1, or lead, mid, lag or next elements continuations
5939  ChangeDirectionMenuItem->Enabled = true;
5940  if(Train.LeadElement > -1)
5941  {
5943  {
5944  ChangeDirectionMenuItem->Enabled = false;
5945  }
5946  if(Track->TrackElementAt(791, Train.LeadElement).Conn[Train.LeadExitPos] > -1)
5947  {
5948  if(Track->TrackElementAt(792, (Track->TrackElementAt(793, Train.LeadElement).Conn[Train.LeadExitPos]))
5949  .TrackType == Continuation)
5950  {
5951  ChangeDirectionMenuItem->Enabled = false;
5952  }
5953  }
5954  }
5955  else
5956  ChangeDirectionMenuItem->Enabled = false;
5957  if(Train.MidElement > -1)
5958  {
5960  {
5961  ChangeDirectionMenuItem->Enabled = false;
5962  }
5963  }
5964  else
5965  ChangeDirectionMenuItem->Enabled = false;
5966  if(Train.LagElement > -1)
5967  {
5969  {
5970  ChangeDirectionMenuItem->Enabled = false;
5971  }
5972  }
5973  RemoveTrainMenuItem->Enabled = true;
5974  SignallerControlStopMenuItem->Enabled = false;
5975  SignallerJoinedByMenuItem->Enabled = false;
5976  RepairFailedTrainMenuItem->Enabled = false;
5977  StepForwardMenuItem->Enabled = false;
5978  MoveForwardsMenuItem->Enabled = false;
5979  PassRedSignalMenuItem->Enabled = false;
5980  if(Train.AbleToMove(0))
5981  {
5982  MoveForwardsMenuItem->Enabled = true;
5984  StepForwardMenuItem->Enabled = true; // added 'if' condition for v1.3.2 due to Carwyn Thomas error,
5985  } // fails on trying to calc AutoSig time delay for resetting signals
5986  if(Train.AbleToMoveButForSignal(0)) // may not be in AutoSigs route but disallow anyway as not needed at continuation
5987  {
5988  PassRedSignalMenuItem->Enabled = true;
5989  StepForwardMenuItem->Enabled = true;
5990  }
5991  TTrain *AdjacentTrain;
5992  if(Train.IsThereAnAdjacentTrain(0, AdjacentTrain))
5993  {
5994  SignallerJoinedByMenuItem->Enabled = true;
5995  }
5996  if(Train.TrainFailed)
5997  {
5998  RepairFailedTrainMenuItem->Enabled = true;
5999  }
6000  }
6001  else // train moving under signaller control - only permit restoration of TT control when stopped as could be in
6002  // mid move, & SetTrainMovementValues only intended to be called when stopped
6003  {
6004  TimetableControlMenuItem->Enabled = false;
6005  ChangeDirectionMenuItem->Enabled = false;
6006  RemoveTrainMenuItem->Enabled = false;
6007  MoveForwardsMenuItem->Enabled = false;
6008  SignallerJoinedByMenuItem->Enabled = false;
6009  RepairFailedTrainMenuItem->Enabled = false;
6010  PassRedSignalMenuItem->Enabled = false;
6011  StepForwardMenuItem->Enabled = false;
6012  SignallerControlStopMenuItem->Enabled = true;
6013  }
6014  }
6015  TrainHeadCodeMenuItem->Caption = Train.HeadCode + ":";
6016  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
6018  PopupMenu->Popup(MainScreen->Left+X, MainScreen->Top+Y+43); //menu stops everything so reset timetable time when restarts,
6019  //new at v2.6.1, displays so that can't inadvertently click on a selection if click twice
6020  //43 is the distance from the top of the screen to the top of TInterface
6021  TrainController->BaseTime = TDateTime::CurrentDateTime();
6023  Utilities->CallLogPop(40);
6024  return;
6025  }
6026  }
6027  }
6028 
6029  if(RouteMode == RouteContinuing) // clear a single element (clears whether use left or right mouse button) +allow in PreStart
6030  {
6031  TrainController->LogEvent("mbRight + RouteContinuing");
6033  Utilities->CallLogPop(41);
6034  return;
6035  }
6036 
6037  else if(RouteCancelFlag) // allow in PreStart
6038  {
6039  TrainController->LogEvent("mbRight + RouteCancelFlag");
6040  Screen->Cursor = TCursor(-11); // Hourglass;
6041  // stop clock as sometimes takes several seconds
6042  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
6044  if(AllRoutes->GetAllRoutesTruncateElement(0, HLoc, VLoc, ConsecSignalsRoute)) // updates LockedRouteClass
6045  {
6046  ClearandRebuildRailway(6); // to replot new shorter route
6047  }
6049  TrainController->BaseTime = TDateTime::CurrentDateTime();
6051  Screen->Cursor = TCursor(-2); // Arrow
6052  }
6053 
6054  else // gap flashing, don't allow to interfere with RouteCancelFlag
6055  {
6056  TrainController->LogEvent("mbRight, GapFlashingInOperOrPreStartMode");
6057  int Position;
6058  TTrackElement TrackElement;
6059  if(Track->FindNonPlatformMatch(4, HLoc, VLoc, Position, TrackElement));
6060  {
6061  if((TrackElement.TrackType == GapJump) && (TrackElement.Conn[0] > -1))
6062  {
6063  if((TrackElement.TrainIDOnElement == -1) && (Track->TrackElementAt(818, TrackElement.Conn[0]).TrainIDOnElement == -1))
6064  { // don't flash if train on either gap element
6065  Track->GapFlashGreenPosition = TrackElement.Conn[0];
6070  Track->GapFlashRedPosition = Position;
6075  Track->GapFlashFlag = true;
6076  }
6077  }
6078  }
6079  Utilities->CallLogPop(42);
6080  return; // covers above else & included here in case any more usermodes added later
6081  }
6082  }
6083 
6084  // deal with gap selection - if no other right button selection - apply for any mode (also included in OperMode above)
6085  TrainController->LogEvent("mbRight, GapFlashingNotOperOrPreStartMode");
6086  int Position;
6087  TTrackElement TrackElement;
6088  if(Track->FindNonPlatformMatch(18, HLoc, VLoc, Position, TrackElement));
6089  {
6090  if((TrackElement.TrackType == GapJump) && (TrackElement.Conn[0] > -1))
6091  {
6092  if((TrackElement.TrainIDOnElement == -1) && (Track->TrackElementAt(819, TrackElement.Conn[0]).TrainIDOnElement == -1))
6093  { // don't flash if train on either gap element
6094  Track->GapFlashGreenPosition = TrackElement.Conn[0];
6098  Track->GapFlashRedPosition = Position;
6102  Track->GapFlashFlag = true;
6103  }
6104  }
6105  }
6106  Utilities->CallLogPop(67);
6107  return; // covers above else & included here in case any more usermodes added later
6108  }
6109 
6110 // Left Mouse Button Functions
6111  if(RouteCancelFlag)
6113  mbLeftDown = true;
6114 
6115  if(Level2TrackMode == AddTrack)
6116  {
6117  TrainController->LogEvent("mbLeft + AddTrack");
6118  Screen->Cursor = TCursor(-11); // Hourglass;
6120  bool TrackLinkingRequiredFlag;
6121  int CurrentTag;
6122  TSpeedButton *TempSpeedButton = 0;
6123  if(CurrentSpeedButton)
6124  {
6125  CurrentTag = CurrentSpeedButton->Tag;
6126  TempSpeedButton = CurrentSpeedButton;
6127  }
6128  else
6129  CurrentTag = 0;
6130  bool InternalChecks = true;
6131  Track->PlotAndAddTrackElement(1, CurrentTag, 0, HLoc, VLoc, TrackLinkingRequiredFlag, InternalChecks);
6132  // above now has extra zero 'Aspect' parameter at v2.2.0 so can distinguish between adding track and pasting
6133  EditMenu->Enabled = true;
6134  if(Track->NamedLocationElementAt(1, HLoc, VLoc))
6135  ClearandRebuildRailway(7); // so named location graphics plotted correctly
6136  if(TrackLinkingRequiredFlag)
6137  {
6138  Track->SetTrackFinished(false);
6139  }
6140  SetTrackBuildImages(10);
6141  SetGapsButton->Enabled = false; // if conditions have changed need to reset buttons, best not calling SetLevel2TrackMode as that
6142  TrackOKButton->Enabled = false; // calls Clearand.. if gridflag set & takes a long time
6143  if(Track->GapsUnset(2))
6144  {
6145  SetGapsButton->Enabled = true;
6146  }
6147  // only enable if there are gaps still to be set (returns false for no track)
6148  else
6149  {
6150  if(!(Track->NoActiveTrack(1)) && !(Track->IsTrackFinished()))
6151  {
6152  TrackOKButton->Enabled = true;
6153  }
6154  // TrackOK only enabled if track exists, there are no unset gaps, and track not finished
6155  }
6156  if(!(Track->IsTrackFinished())) // can only set lengths for several elements together if TrackFinished
6157  {
6158  SetLengthsButton->Enabled = false;
6159  }
6160  if(TempSpeedButton) // restore button if was pressed
6161  {
6162  CurrentSpeedButton = TempSpeedButton;
6163  CurrentSpeedButton->Down = true;
6164  }
6165  Screen->Cursor = TCursor(-2); // Arrow
6166  Utilities->CallLogPop(44);
6167  return;
6168  }
6169 
6170  else if(Level2TrackMode == AddGraphic)
6171  {
6172  TrainController->LogEvent("mbLeft + AddGraphic");
6173  ResetChangedFileDataAndCaption(24, false);
6174  TUserGraphicItem NewGI;
6175  TTrack::TUserGraphicMap::iterator UGMIt = Track->UserGraphicMap.find(SelectedGraphicFileName);
6176  if(UGMIt != Track->UserGraphicMap.end()) // if it is the end then nothing was found
6177  {
6178  NewGI.UserGraphic = UGMIt->second;
6179  NewGI.Width = UGMIt->second->Width;
6180  NewGI.Height = UGMIt->second->Height;
6182  NewGI.HPos = X + (Display->DisplayOffsetH * 16);
6183  NewGI.VPos = Y + (Display->DisplayOffsetV * 16);
6184  Track->UserGraphicVector.push_back(NewGI);
6185  Display->PlotAndAddUserGraphic(1, NewGI);
6186  }
6187  else
6188  {
6189  ShowMessage("Unable to find graphic file " + SelectedGraphicFileName + ". Check it still exists.");
6190  Utilities->CallLogPop(2195);
6191  return;
6192  }
6193  MoveTextOrGraphicButton->Enabled = true;
6194  EditMenu->Enabled = true;
6195  Utilities->CallLogPop(2182);
6196  return;
6197  }
6198 
6199  else if(Level2TrackMode == AddLocationName)
6200  {
6201  TrainController->LogEvent("mbLeft + AddLocationName");
6203  bool FoundFlag;
6204  TTrackElement TrackElement;
6205  AnsiString NameString;
6206  TTrack::TIMPair InactivePair = Track->GetVectorPositionsFromInactiveTrackMap(1, HLoc, VLoc, FoundFlag);
6207  if(!FoundFlag)
6208  {
6209  Utilities->CallLogPop(45);
6210  return; // inactive element not found (has to be a platform or named non-station location, can't select any other element)
6211  }
6212  TTrackElement& InactiveTrackElement1 = Track->InactiveTrackElementAt(28, InactivePair.first);
6213  TTrackElement& InactiveTrackElement2 = Track->InactiveTrackElementAt(29, InactivePair.second); // may be same element if only 1
6214  TTrackElement& ValidElement = InactiveTrackElement1;
6215  unsigned int ValidPosition;
6216  if((InactiveTrackElement1.TrackType != Platform) && (InactiveTrackElement2.TrackType != Platform) &&
6217  (InactiveTrackElement1.TrackType != NamedNonStationLocation) && (InactiveTrackElement2.TrackType != NamedNonStationLocation) &&
6218  (InactiveTrackElement1.TrackType != Concourse) && (InactiveTrackElement2.TrackType != Concourse))
6219  {
6220  Utilities->CallLogPop(46);
6221  return; // element not valid
6222  }
6223  if((InactiveTrackElement1.TrackType == Platform) || (InactiveTrackElement1.TrackType == NamedNonStationLocation) ||
6224  (InactiveTrackElement1.TrackType == Concourse))
6225  {
6226  ValidElement = InactiveTrackElement1;
6227  ValidPosition = InactivePair.first;
6228  }
6229  else if((InactiveTrackElement2.TrackType == Platform) || (InactiveTrackElement2.TrackType == NamedNonStationLocation) ||
6230  (InactiveTrackElement2.TrackType == Concourse))
6231  {
6232  ValidElement = InactiveTrackElement2;
6233  ValidPosition = InactivePair.second;
6234  }
6235  // now have required element as ValidElement & position in InactiveTrackvector as ValidPosition
6236 
6237  // put a square box round element to show selection
6238  Display->Rectangle(0, HLoc * 16, VLoc * 16, clB0G0R5, 0, 2);
6239  LocationNameTextBox->Visible = true;
6240  LocationNameTextBox->SetFocus();
6241  NameString = Track->GetLocationName(ValidPosition);
6242  LocationNameTextBox->Text = NameString;
6243  InfoPanel->Visible = true;
6244  InfoPanel->Caption = "NAMING LOCATIONS: Enter name, 'Carriage Return' to accept, 'Escape' to quit";
6245 
6246  Track->LNPendingList.clear();
6247  Track->LNPendingList.insert(Track->LNPendingList.end(), ValidPosition);
6248  Level2TrackMode = NoTrackMode; // if leave as AddLocationName can select other squares before enter name
6249  Utilities->CallLogPop(47);
6250  return;
6251  }
6252 
6253  else if(Level2TrackMode == DistanceStart) // new for extended distances - similar to !PrefDirContinuing
6254  // prior to selecting start element
6255  {
6256  TrainController->LogEvent("mbLeft + DistanceStart");
6258  if(ConstructPrefDir->GetPrefDirStartElement(0, HLoc, VLoc))
6259  {
6262  SetLevel1Mode(65);
6264  SetLevel2TrackMode(30);
6265  }
6266  Utilities->CallLogPop(48);
6267  return;
6268  }
6269 
6270  else if(Level2TrackMode == DistanceContinuing) // new for extended distances - similar to PrefDirContinuing
6271  // prior to selecting finish element
6272  {
6273  TrainController->LogEvent("mbLeft + DistanceContinuing");
6275  bool FinishElement = false, LeadingPointsAtLastElement = false;
6276  Screen->Cursor = TCursor(-11); // Hourglass;
6277  if((ConstructPrefDir->PrefDirSize() != 1) || (ConstructPrefDir->GetFixedPrefDirElementAt(181, 0).HLoc != HLoc) ||
6278  (ConstructPrefDir->GetFixedPrefDirElementAt(182, 0).VLoc != VLoc))
6279  { // not same as start element
6280  if(ConstructPrefDir->GetNextPrefDirElement(0, HLoc, VLoc, FinishElement))
6281  {
6284  ConstructPrefDir->CalcDistanceAndSpeed(1, OverallDistance, OverallSpeedLimit, LeadingPointsAtLastElement);
6285  if(FinishElement)
6286  {
6287  TrackLengthPanel->Visible = true;
6288  TrackLengthPanel->SetFocus();
6289  InfoPanel->Visible = true;
6290  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Set values (overall length), or right click to cancel/truncate";
6291  RestoreAllDefaultLengthsButton->Enabled = true;
6292  ResetDefaultLengthButton->Enabled = true;
6293  LengthOKButton->Enabled = true;
6294  DistanceBox->Text = AnsiString(OverallDistance);
6295  if(OverallSpeedLimit > -1)
6296  SpeedLimitBox->Text = AnsiString(OverallSpeedLimit);
6297  else
6298  SpeedLimitBox->Text = "Mixed";
6300  Screen->Cursor = TCursor(-2); // Arrow
6301  Utilities->CallLogPop(1527);
6302  return;
6303  }
6304  else
6305  {
6306  if(!LeadingPointsAtLastElement)
6307  {
6308  TrackLengthPanel->Visible = true;
6309  TrackLengthPanel->SetFocus();
6310  InfoPanel->Visible = true;
6311  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Continue or set values (overall length), or right click to cancel/truncate";
6312  RestoreAllDefaultLengthsButton->Enabled = true;
6313  ResetDefaultLengthButton->Enabled = true;
6314  LengthOKButton->Enabled = true;
6315  DistanceBox->Text = AnsiString(OverallDistance);
6316  if(OverallSpeedLimit > -1)
6317  SpeedLimitBox->Text = AnsiString(OverallSpeedLimit);
6318  else
6319  SpeedLimitBox->Text = "Mixed";
6320  // Level2TrackMode = DistanceContinuing;
6321  // SetLevel2TrackMode();
6322  }
6323  else
6324  {
6325  TrackLengthPanel->Visible = true;
6326  TrackLengthPanel->SetFocus();
6327  InfoPanel->Visible = true;
6328  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Can't end on leading points, need to continue or truncate";
6329  RestoreAllDefaultLengthsButton->Enabled = false;
6330  ResetDefaultLengthButton->Enabled = false;
6331  LengthOKButton->Enabled = false;
6332  // Level2TrackMode = DistanceContinuing;
6333  // SetLevel2TrackMode();
6334  }
6335  }
6336  }
6337  }
6338  else // same as start element
6339  {
6342  SetLevel2TrackMode(54);
6343  Screen->Cursor = TCursor(-2); // Arrow
6344  Utilities->CallLogPop(1713);
6345  return;
6346  }
6348  Screen->Cursor = TCursor(-2); // Arrow
6349  Utilities->CallLogPop(1490);
6350  return;
6351  }
6352 
6353  else if(Level2TrackMode == GapSetting)
6354  {
6355  TrainController->LogEvent("mbLeft + GapSetting");
6357  // HighLightOneGap already called once from SetLevel2TrackMode so have all gap element values set
6358  // & it is highlighted
6359  if(!(Track->FindSetAndDisplayMatchingGap(1, HLoc, VLoc)))
6360  {
6361  Utilities->CallLogPop(50);
6362  return; // true if finds one
6363  }
6364  InfoPanel->Visible = true;
6365  InfoPanel->Caption = "CONNECTING GAPS: Connecting element selected";
6366  Display->Update(); // resurrected when Update() dropped from PlotOutput etc
6367  Delay(0, 500); // 500 msec delay before next selection requested
6368 
6369  // ClearandRebuildRailway(8);//get rid of gap selections
6370  // need to call this later when new gap displayed, else old gap remains
6371 
6372  // now back to highlighting next gap
6373  // bool LocError = false;
6374  if(!(HighLightOneGap(1, HLoc, VLoc)))
6375  {
6376  // all gaps set
6377  ShowMessage("All gaps set");
6378  if(Level2TrackMode == AddTrack)
6379  {
6381  SetLevel1Mode(66);
6382  SetLevel2TrackMode(31);
6383  }
6384  else
6385  {
6387  SetLevel1Mode(37);
6388  }
6389  ClearandRebuildRailway(9); // get rid of last gap ellipse
6390  Utilities->CallLogPop(51);
6391  return;
6392  }
6393  // here if one gap highlighted so return to user to allow corresponding gap to be selected
6394  // by another call to MainScreenMouseDown
6395  }
6396 
6397  else if(Level2TrackMode == AddText)
6398  {
6399  TrainController->LogEvent("mbLeft + AddText");
6401  // X & Y are relative to Display output, but TextBox is placed relative to Form
6402  // if mouse position on first character of an existing piece of text reload it into the editor
6403 
6404  bool TextFoundFlag = false;
6405  int TrueX = 0, TrueY = 0;
6406  AnsiString ExistingText = "";
6408  TFont *ExistingTextFont = new TFont;
6409  int ExistingTextHPos = 0, ExistingTextVPos = 0;
6410  Track->GetTruePositionsFromScreenPos(1, TrueX, TrueY, X, Y);
6411  if(!TextHandler->TextVector.empty())
6412  {
6413  for(TextPtr = (TextHandler->TextVector.end() - 1); TextPtr >= TextHandler->TextVector.begin(); TextPtr--)
6414  {
6415  if((TrueX >= TextPtr->HPos) && (TrueX < (TextPtr->HPos + abs(TextPtr->Font->Height))) && (TrueY >= TextPtr->VPos) && (TrueY <
6416  (TextPtr->VPos + abs(TextPtr->Font->Height))))
6417  {
6418  ExistingText = TextPtr->TextString;
6419  ExistingTextFont->Assign(TextPtr->Font);
6420  ExistingTextHPos = TextPtr->HPos;
6421  ExistingTextVPos = TextPtr->VPos;
6422  TextFoundFlag = true;
6423  TextHandler->TextErase(9, TrueX, TrueY, ExistingText);
6424  break;
6425  } // if ....
6426  } // for TextPtr...
6427  } // if !TextVector...
6428 
6429  if(TextFoundFlag)
6430  {
6431  TextBox->Left = ExistingTextHPos + Display->Left() - (Display->DisplayOffsetH * 16) - 3;
6432  TextBox->Top = ExistingTextVPos + Display->Top() - (Display->DisplayOffsetV * 16) - 3;
6433  TextBox->Font->Assign(ExistingTextFont);
6434  Display->SetFont(ExistingTextFont);
6435  Text_X = ExistingTextHPos;
6436  Text_Y = ExistingTextVPos;
6437  }
6438  else
6439  {
6440  TextBox->Left = (TextOrUserGraphicGridVal * div((Display->Left() + X), TextOrUserGraphicGridVal).quot) - 3;
6441  TextBox->Top = (TextOrUserGraphicGridVal * div((Display->Top() + Y), TextOrUserGraphicGridVal).quot) - 3;
6442  TextBox->Font->Assign(Display->GetFont());
6443  Text_X = TextOrUserGraphicGridVal * div(NoOffsetX, TextOrUserGraphicGridVal).quot;
6444  Text_Y = TextOrUserGraphicGridVal * div(NoOffsetY, TextOrUserGraphicGridVal).quot;
6445  }
6446  TextBox->Visible = true;
6447  TextBox->SetFocus();
6448  if(TextFoundFlag)
6449  TextBox->Text = ExistingText;
6450  else
6451  TextBox->Text = "New Text: CR=end, ESC=quit";
6452  TextBox->Width = (abs(TextBox->Font->Height) * TextBox->Text.Length() * 0.7);
6453  TextBox->SelectAll();
6454  delete ExistingTextFont;
6455  ClearandRebuildRailway(29); // to remove old text if replaced
6457  Utilities->CallLogPop(1775);
6458  return; // If text input go no further
6459  }
6460 
6462  {
6463  TrainController->LogEvent("mbLeft + MoveTextOrGraphic");
6465  // int HPosInput;// = X + (Display->DisplayOffsetH * 16);
6466  // int VPosInput;// = Y + (Display->DisplayOffsetV * 16);
6467  // Track->GetTruePositionsFromScreenPos(HPosInput, VPosInput, X, Y);
6468  // StartX = X + (Display->DisplayOffsetH * 16);
6469  // StartY = Y + (Display->DisplayOffsetV * 16);
6472  if(!TextFoundFlag) // give precedence to text
6473  {
6475  }
6476  Utilities->CallLogPop(53);
6477  return; // if text move selected don't permit anything else
6478  }
6479 
6480  else if(Level2TrackMode == TrackSelecting)
6481 /* When 'select' chosen from the Edit menu (only available in 'AddTrack') conditions are set ready to enclose a rectangular screen area
6482  using MouseMove. When MouseDown occurs the starting point is marked (wrt whole railway, not just the screen) and stored in
6483  SelectStartPair. If the mouse button is released and a new start position selected then the earlier one is discarded. Providing the
6484  button is held down subsequent actions occur during MouseMove (to display the changing rectangle) and MouseUp to define the final
6485  selected rectangle.
6486 */
6487  {
6488  TrainController->LogEvent("mbLeft + TrackSelecting");
6489  ClearandRebuildRailway(10); // to get rid of earlier rectangles
6490  SelectStartPair.first = HLoc;
6491  SelectStartPair.second = VLoc;
6492  }
6493 
6494  else if((Level2TrackMode == CopyMoving) || (Level2TrackMode == CutMoving))
6495 /* The same actions apply on MouseDown whether Copy or Cut selected from the menu. First the horizontal and vertical mouse position is
6496  checked and unless it lies within the selected rectangle and not within 4 pixels of an edge the pickup fails and the function returns.
6497  Otherwise flag SelectPickedUp is set to true (to allow it to move during MouseMove and remain in place at MouseUp) and the mouse position
6498  is saved in SelectBitmapMouseLocX & Y for use later in MouseMove & MouseUp.
6499 */
6500  {
6501  TrainController->LogEvent("mbLeft + CopyMoving or CutMoving");
6503  if((X < ((SelectBitmapHLoc - Display->DisplayOffsetH) * 16) + 4) ||
6504  (X > ((SelectBitmapHLoc + (SelectBitmap->Width / 16) - Display->DisplayOffsetH) * 16) - 4))
6505  {
6506  SelectPickedUp = false;
6507  Utilities->CallLogPop(54);
6508  return; // within 4 pixels of outside of horizontal area (4 pixels are so can't push selection off edge of screen)
6509  }
6510  if((Y < ((SelectBitmapVLoc - Display->DisplayOffsetV) * 16) + 4) ||
6511  (Y > ((SelectBitmapVLoc + (SelectBitmap->Height / 16) - Display->DisplayOffsetV) * 16) - 4))
6512  {
6513  SelectPickedUp = false;
6514  Utilities->CallLogPop(55);
6515  return; // within 4 pixels of outside of vertical area (4 pixels are so can't push selection off edge of screen)
6516  }
6517  else
6518  {
6519  SelectPickedUp = true;
6520  }
6523  }
6524 
6526  {
6527  TrainController->LogEvent("mbLeft + != PrefDirContinuing");
6528  ResetChangedFileDataAndCaption(15, false);
6529 // RlyFile = false; - don't alter this just for PrefDir changes
6530  if(ConstructPrefDir->GetPrefDirStartElement(1, HLoc, VLoc))
6531  {
6535  }
6536  Utilities->CallLogPop(56);
6537  return;
6538  }
6539 
6541  {
6542  TrainController->LogEvent("mbLeft + PrefDirContinuing");
6543  ResetChangedFileDataAndCaption(16, false);
6544 // RlyFile = false; - don't alter this just for PrefDir changes
6545  bool FinishElement;
6546  Screen->Cursor = TCursor(-11); // Hourglass;
6547  if((ConstructPrefDir->PrefDirSize() != 1) || (ConstructPrefDir->GetFixedPrefDirElementAt(183, 0).HLoc != HLoc) ||
6548  (ConstructPrefDir->GetFixedPrefDirElementAt(184, 0).VLoc != VLoc))
6549  { // not same as start element
6550  if(ConstructPrefDir->GetNextPrefDirElement(1, HLoc, VLoc, FinishElement))
6551  {
6553  if(FinishElement)
6554  {
6555  ShowMessage("Preferred direction added");
6558  SetLevel1Mode(16);
6559  Screen->Cursor = TCursor(-2); // Arrow
6560  Utilities->CallLogPop(57);
6561  return;
6562  }
6563  else
6564  {
6567  }
6568  // set again since 1st time
6569  // PrefDir vector only had start element & Truncate wasn't enabled, also need
6570  // to do the checks for Loop & End for each element as it is added
6571  }
6572  }
6573  else // same as start element
6574  {
6577  SetLevel1Mode(121);
6578  Screen->Cursor = TCursor(-2); // Arrow
6579  Utilities->CallLogPop(1714);
6580  return;
6581  }
6582  Screen->Cursor = TCursor(-2); // Arrow
6583  Utilities->CallLogPop(58);
6584  return;
6585  }
6586 
6588  {
6589  TrainController->LogEvent("mbLeft + PrefDirSelecting");
6590  ClearandRebuildRailway(56); // to get rid of earlier rectangles
6591  SelectStartPair.first = HLoc;
6592  SelectStartPair.second = VLoc;
6593  }
6594 
6595  else if(Level1Mode == OperMode)
6596  {
6597  if((Level2OperMode == Operating) && CallingOnButton->Down && CallingOnButton->Enabled)
6598  {
6599  TrainController->LogEvent("mbLeft + Operating & CallingOnButton->Down");
6600  int Position;
6601  TTrackElement TrackElement;
6602  if(Track->FindNonPlatformMatch(2, HLoc, VLoc, Position, TrackElement))
6603  {
6604  if(TrackElement.TrackType != SignalPost)
6605  {
6606  CallingOnButton->Down = false;
6607 // InfoPanel->Visible = false; //dropped at v1.3.0, not sure what purpose intended to serve but don't want to lose the info panel as did with this here also added line below to reset
6609  Utilities->CallLogPop(59);
6610  return;
6611  }
6612  for(unsigned int x = 0; x < TrainController->TrainVector.size(); x++)
6613  {
6615  {
6617  x).LeadExitPos] == Position) && (TrackElement.Config[Track->TrackElementAt(429, TrainController->TrainVectorAt(28,
6619  {
6620  // found it!
6621 /*
6622  if(TrackElement.SpeedTag == 68)
6623  {
6624  Display->PlotOutput(0, (HLoc * 16), (VLoc * 16), RailGraphics->bm68CallingOn);
6625  }
6626  if(TrackElement.SpeedTag == 69)
6627  {
6628  Display->PlotOutput(1, (HLoc * 16), (VLoc * 16), RailGraphics->bm69CallingOn);
6629  }
6630  if(TrackElement.SpeedTag == 70)
6631  {
6632  Display->PlotOutput(2, (HLoc * 16), (VLoc * 16), RailGraphics->bm70CallingOn);
6633  }
6634  if(TrackElement.SpeedTag == 71)
6635  {
6636  Display->PlotOutput(3, (HLoc * 16), (VLoc * 16), RailGraphics->bm71CallingOn);
6637  }
6638  if(TrackElement.SpeedTag == 72)
6639  {
6640  Display->PlotOutput(4, (HLoc * 16), (VLoc * 16), RailGraphics->bm72CallingOn);
6641  }
6642  if(TrackElement.SpeedTag == 73)
6643  {
6644  Display->PlotOutput(5, (HLoc * 16), (VLoc * 16), RailGraphics->bm73CallingOn);
6645  }
6646  if(TrackElement.SpeedTag == 74)
6647  {
6648  Display->PlotOutput(6, (HLoc * 16), (VLoc * 16), RailGraphics->bm74CallingOn);
6649  }
6650  if(TrackElement.SpeedTag == 75)
6651  {
6652  Display->PlotOutput(7, (HLoc * 16), (VLoc * 16), RailGraphics->bm75CallingOn);
6653  }
6654 */
6655  Track->TrackElementAt(430, Position).CallingOnSet = true;
6656  Track->PlotSignal(13, Track->TrackElementAt(893, Position), Display);
6657 // added at v 1.3.0 in place of the above to ensure ground signals (as well as others) plot correctly for proceed
6658  // have to call after CallingOnSet becomes true & can't use TrackElement as that still has CallingOnSet false
6659  ClearandRebuildRailway(69); // added at v1.3.0 to replot route on element after PlotSignal above
6662  CallingOnButton->Down = false;
6664 
6665 // set an unrestricted route into the station (just to the first platform) from the stop signal (note that it may be last in an autosigs
6666 // route) but remove any single route elements first (can't reach here if constructing a route), else may try to extend a route that
6667 // has been removed (only a precaution, shouldn't cause any probs whether single route set or not)
6668  for(unsigned int x = 0; x < AllRoutes->AllRoutesSize(); x++)
6669  {
6670  if(AllRoutes->GetFixedRouteAt(192, x).PrefDirSize() == 1)
6671  {
6672  // only allow route element to be removed if not selected for a route start otherwise
6673  // StartSelectionRouteID will be set & will fail at convert
6675  {
6677  AllRoutes->RemoveRouteElement(21, PDE.HLoc, PDE.VLoc, PDE.GetELink());
6678  TrainController->LogEvent("SingleRouteElementRemovedDuringCallon, H = " + AnsiString(PDE.HLoc) + ", V = " +
6679  AnsiString(PDE.VLoc));
6680  }
6681  }
6682  }
6683 
6684 // find the correct entry in CallonVector - i.e. where Position == RouteStartEntry
6685  for(unsigned int x = 0; x < AllRoutes->CallonVector.size(); x++)
6686  {
6687  if(AllRoutes->CallonVector.at(x).RouteStartPosition == Position)
6688  { // found it
6689  if(!(AllRoutes->CallonVector.at(x).RouteOrPartRouteSet))
6690  // if RouteOrPartRouteSet false then set an unrestricted route into platform
6691  {
6692  bool PointsChanged = false;
6693  IDInt ReqPosRouteID(-1);
6694  TOneRoute *NewRoute = new TOneRoute;
6695  bool CallonTrue = true;
6696  bool ConsecSignalsRouteFalse = false;
6697  if(NewRoute->GetNonPreferredRouteStartElement(1,
6698  Track->TrackElementAt(841, AllRoutes->CallonVector.at(x).RouteStartPosition).HLoc,
6699  Track->TrackElementAt(842, AllRoutes->CallonVector.at(x).RouteStartPosition).VLoc, ConsecSignalsRouteFalse,
6700  CallonTrue))
6701  {
6702  if(NewRoute->GetNextNonPreferredRouteElement(1,
6703  Track->TrackElementAt(843, AllRoutes->CallonVector.at(x).PlatformPosition).HLoc,
6704  Track->TrackElementAt(844, AllRoutes->CallonVector.at(x).PlatformPosition).VLoc, ConsecSignalsRouteFalse,
6705  CallonTrue, ReqPosRouteID, PointsChanged))
6706  {
6707  if(!PointsChanged) // shouldn't be changed, something wrong if true so don't plot route
6708  {
6709  NewRoute->ConvertAndAddNonPreferredRouteSearchVector(3, ReqPosRouteID);
6710  ClearandRebuildRailway(67); // to plot the route (only finds one so won't call repeatedly)
6711  }
6712  }
6713  }
6714  delete NewRoute;
6715  }
6716  }
6717  }
6718 // InfoPanel->Visible = false;
6719  Utilities->CallLogPop(60);
6720  return;
6721  }
6722  }
6723  }
6724  }
6725  CallingOnButton->Down = false;
6727  Utilities->CallLogPop(61);
6728  return;
6729  }
6730 /* get 1st element, first check if selected points, not in existing route, & in RouteNotStarted mode
6731  if so, set all the flash values, Track->PointFlashFlag & start time, then exit for flasher to take over.
6732  If any of above conditions not met then treat as route selection, setting route flasher if
6733  route continuing.
6734 */
6735 
6736  if((Level2OperMode == Operating) || (Level2OperMode == PreStart)) // not 'else if' as both may apply
6737  // disallow route setting if paused
6738  {
6739  if(Level2OperMode == PreStart)
6740  {
6741  PointsFlashDuration = 0.0;
6744  }
6745  else
6746  {
6747  float TempSpeedVal = 1; // added for v2.3.0 to keep durations same as x1 values for slow speeds
6748  if(TTClockSpeed < 1)
6749  TempSpeedVal = TTClockSpeed;
6750  PointsFlashDuration = AllRoutes->PointsDelay * TempSpeedVal;
6753  }
6754  if(RouteMode == RouteNotStarted)
6755  {
6756  TrainController->LogEvent("mbLeft + RouteNotStarted");
6757  int Position;
6758  TTrackElement TrackElement;
6759  if(Track->FindNonPlatformMatch(3, HLoc, VLoc, Position, TrackElement))
6760  {
6761  if((TrackElement.TrackType == Points) && !(AllRoutes->TrackIsInARoute(1, Position, 0))
6763  // Flash selected points & changeover if appropriate
6764  // need !Track->PointFlashFlag to prevent another point being selected while another is flashing, & !Track->RouteFlashFlag
6765  // to ensure user only does one thing at a time
6766  {
6767  if(TrackElement.TrainIDOnElement > -1)
6768  {
6769  TrainController->StopTTClockMessage(1, "Can't change points under a train!");
6770  Utilities->CallLogPop(62);
6771  return;
6772  }
6773  PointFlash->SetScreenHVSource(1, TrackElement.HLoc * 16, TrackElement.VLoc * 16);
6774 
6775 /*
6776  This used to try to allow any linked trailing edges to cause both points to change, but no good if
6777  there are two adjacent crossovers, where both trailing edges are linked to two different points.
6778  The wrong link might be chosen. Also doubtful if applying a strict order of checks would work, since
6779  may be obscure configurations that would be wrong. This function bypasses the MatchingPoint check, which
6780  ensures that there are no obscure links. Hence better to stick with original.
6781 
6782  //check if trailing edge linked to another point trailing edge
6783  int DivergingPosition = TrackElement.Conn[1];
6784  TTrackElement DivergingElement = Track->TrackElementAt(431, TrackElement.Conn[1]);
6785  DivergingPointVectorPosition = -1;
6786  if((DivergingElement.TrackType == Points) &&
6787  ((DivergingElement.Conn[1] == Position) || (DivergingElement.Conn[3] == Position)))
6788  {
6789  if(AllRoutes->TrackIsInARoute(, DivergingPosition))
6790  {
6791  ShowMessage("Linked points Locked");
6792  }
6793  else DivergingPointVectorPosition = DivergingPosition;
6794  }
6795  else
6796  {
6797  DivergingPosition = TrackElement.Conn[3];
6798  DivergingElement = Track->TrackElementAt(432, TrackElement.Conn[3]);
6799  if((DivergingElement.TrackType == Points) &&
6800  ((DivergingElement.Conn[1] == Position) || (DivergingElement.Conn[3] == Position)))
6801  {
6802  if(AllRoutes->TrackIsInARoute(, DivergingPosition))
6803  {
6804  ShowMessage("Linked points locked");
6805  }
6806  else DivergingPointVectorPosition = DivergingPosition;
6807  }
6808  }
6809  Track->PointFlashFlag = true;
6810  PointFlashVectorPosition = Position;
6811  PointFlashStartTime = TrainController->TTClockTime;
6812  [close curly bracket - if include it matches earlier non-commented one!]
6813 */
6814  TTrackElement DivergingElement = Track->TrackElementAt(433, TrackElement.Conn[3]);
6815  int DivergingPosition = TrackElement.Conn[3];
6816  if((DivergingElement.TrackType == Points) && (DivergingElement.Conn[3] == Position) && (Track->MatchingPoint(1, Position,
6817  DivergingPosition))) // full match inc same attributes
6818  {
6819  if(AllRoutes->TrackIsInARoute(4, DivergingPosition, 0))
6820  {
6821  TrainController->StopTTClockMessage(2, "Linked points locked");
6822  }
6823  else
6824  {
6825  Track->PointFlashFlag = true;
6826  PointFlashVectorPosition = Position;
6827  DivergingPointVectorPosition = DivergingPosition;
6829  }
6830  }
6831  else // no matching point, just change this point
6832  {
6833  Track->PointFlashFlag = true;
6834  PointFlashVectorPosition = Position;
6837  }
6838  }
6839 
6840  else if(Track->IsLCAtHV(59, HLoc, VLoc) && !Track->PointFlashFlag && !Track->RouteFlashFlag)//level crossing added at v2.6.0 to allow manual LC changing
6841  {
6842  if(Track->GetInactiveTrackElementFromTrackMap(5, HLoc, VLoc).Attribute != 2) // 2 = LC changing state, can't click if changing
6843  {
6844  Track->LCChangeFlag = true;
6845  bool TrainPresent = false;
6846  if(Track->IsLCBarrierDownAtHV(4, HLoc, VLoc)) //if true then raise barriers
6847  {
6848  //first need to identify the LC in the BarriersDownVector
6849  int BDVectorPos = -1;
6850  if(Track->AnyLinkedBarrierDownVectorManual(1, HLoc, VLoc, BDVectorPos)) //looking for same position & manually closed
6851  { //this largely copied from ClockTimer2
6853  Track->BarriersDownVector.at(BDVectorPos).VLoc, TrainPresent)) //returns true for route or train, and TrainPresent true if train on LC
6854  {
6855  TTrack::TActiveLevelCrossing CLC = Track->BarriersDownVector.at(BDVectorPos);
6856  // check if have exceeded the allowance (3 minutes for a train having passed or 0 for not) and add it to the overall excess time
6857  TDateTime TempExcessLCDownTime;
6858  if(Track->BarriersDownVector.at(BDVectorPos).ReducedTimePenalty) //this set in ClockTimer2, relies on train being on LC for >= 1 second or won't
6859  { //get the 3 mins allowance - hard to imagine will pass in less than a second!
6860  TempExcessLCDownTime = TrainController->TTClockTime - CLC.StartTime - TDateTime(180.0 / 86400);
6861  }
6862  else
6863  {
6864  TempExcessLCDownTime = TrainController->TTClockTime - CLC.StartTime;
6865  }
6866  if(TempExcessLCDownTime > TDateTime(0))
6867  {
6868  TrainController->ExcessLCDownMins += (double(TempExcessLCDownTime) * 1440);
6869  }
6870  CLC.StartTime = TrainController->TTClockTime; // reset these 3 members
6873  Track->SetLinkedLevelCrossingBarrierAttributes(7, CLC.HLoc, CLC.VLoc, 2); // set attr to 2 for changing state
6874  Track->ChangingLCVector.push_back(CLC);
6875  Track->BarriersDownVector.erase(Track->BarriersDownVector.begin() + BDVectorPos);
6876  }
6877  }
6878  }
6879  else //lowering
6880  {
6881  //this largely copied from SetLCChangeValues
6882  TTrack::TActiveLevelCrossing ALC; //constructor sets ReducedTimePenalty to false
6883  ALC.HLoc = HLoc;
6884  ALC.VLoc = VLoc;
6886  ALC.BaseElementSpeedTag = TrackElement.SpeedTag;
6889  ALC.ConsecSignals = 2;
6890  Track->SetLinkedManualLCs(0, HLoc, VLoc); //this sets all linked LC ConsecSignals values to 2 for manually lowered - differs from SetLCChangeValues which uses the route type
6891  Track->SetLinkedLevelCrossingBarrierAttributes(6, HLoc, VLoc, 2);//set attr to 2 for changing state
6892  Track->ChangingLCVector.push_back(ALC);
6894  {
6895  AnsiString Message = AnsiString("This will open the level crossing manually (it will show in green).\n\nA manually opened"
6896  " level crossing must be manually closed, and as soon as possible to avoid time penalties.\n\n"
6897  "This message will not be shown again.");
6898  TrainController->StopTTClockMessage(93, Message);
6900  }
6901  }
6902  }
6903  }
6904  else // route start
6905  {
6906  if(AutoSigsFlag)
6907  {
6908  AutoRouteStartMarker->SetScreenHVSource(2, TrackElement.HLoc * 16, TrackElement.VLoc * 16);
6910  }
6911  else if(ConsecSignalsRoute)
6912  {
6913  SigRouteStartMarker->SetScreenHVSource(3, TrackElement.HLoc * 16, TrackElement.VLoc * 16);
6915  }
6916  else
6917  {
6918  NonSigRouteStartMarker->SetScreenHVSource(4, TrackElement.HLoc * 16, TrackElement.VLoc * 16);
6920  }
6921  if(PreferredRoute)
6922  {
6923  if(!Track->PointFlashFlag && !Track->RouteFlashFlag) // don't allow a route to start if a point changing or
6924  // another route building
6925  {
6926  ConstructRoute->ClearRoute(); // in case not empty though should be
6928  {
6929  if(AutoSigsFlag)
6931  else
6934  InfoPanel->Visible = true;
6935  if(Level2OperMode == PreStart)
6936  InfoPanel->Caption = "PRE-START: Select next route location";
6937  else
6938  InfoPanel->Caption = "OPERATING: Select next route location";
6939  }
6940  }
6941  Utilities->CallLogPop(63);
6942  return;
6943  }
6944  else // nonpreferred route
6945  {
6946  if(!Track->PointFlashFlag && !Track->RouteFlashFlag) // don't allow a route to start if a point changing or
6947  // another route building
6948  {
6949  ConstructRoute->ClearRoute(); // in case not empty though should be
6950  bool CallonFalse = false;
6951  if(ConstructRoute->GetNonPreferredRouteStartElement(0, HLoc, VLoc, ConsecSignalsRoute, CallonFalse))
6952  {
6955  InfoPanel->Visible = true;
6956  if(Level2OperMode == PreStart)
6957  InfoPanel->Caption = "PRE-START: Select next route location";
6958  else
6959  InfoPanel->Caption = "OPERATING: Select next route location";
6960  }
6961  }
6962  Utilities->CallLogPop(64);
6963  return;
6964  } // NonPreferred route
6965  } // TrackType != Points
6966  } // if(Track->FindNonPlatformMatch(HLoc, VLoc, Position, TrackElement))
6967  } // if(RouteMode == RouteNotStarted)
6968  else // RouteContinuing
6969  {
6970  TrainController->LogEvent("mbLeft + RouteContinuing");
6971  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
6974  AutoRouteStartMarker->PlotOriginal(14, Display); // if overlay not plotted will ignore
6975  SigRouteStartMarker->PlotOriginal(15, Display); // if overlay not plotted will ignore
6976  NonSigRouteStartMarker->PlotOriginal(16, Display); // if overlay not plotted will ignore
6977  Screen->Cursor = TCursor(-11); // Hourglass - also set to an hourglass when flashing, after found required
6978  // element, but this sets it to an hourglass while searching
6979  bool PointsChanged = false;
6980  if(PreferredRoute)
6981  {
6982  // route added to AllRoutes in GetNextRouteElement if valid
6983  // int ReqPosRouteNumber;
6985  ConstructRoute->ReqPosRouteID, PointsChanged))
6986  {
6987  Track->RouteFlashFlag = true;
6988  PreferredRouteFlag = true;
6989  float TempSpeedVal = 1; // added for v2.3.0 to keep durations same as x1 values for slow speeds
6990  if(TTClockSpeed < 1)
6991  TempSpeedVal = TTClockSpeed;
6992  if(Level2OperMode == PreStart)
6993  RouteFlashDuration = 0.0;
6994  else if(PointsChanged)
6995  RouteFlashDuration = AllRoutes->PointsDelay * TempSpeedVal;
6996  else
6997  RouteFlashDuration = AllRoutes->SignalsDelay * TempSpeedVal;
6998  ConstructRoute->SetRouteFlashValues(1, AutoSigsFlag, true); // true for ConsecSignalsRoute
7000  }
7001  else
7002  {
7004  }
7005  Screen->Cursor = TCursor(-2); // Arrow
7006  TrainController->BaseTime = TDateTime::CurrentDateTime();
7008  Utilities->CallLogPop(65);
7009  return;
7010  }
7011  else
7012  {
7013  bool CallonFalse = false;
7015  PointsChanged))
7016  {
7017  Track->RouteFlashFlag = true;
7018  PreferredRouteFlag = false;
7019  float TempSpeedVal = 1; // added for v2.3.0 to keep durations same as x1 values for slow speeds
7020  if(TTClockSpeed < 1)
7021  TempSpeedVal = TTClockSpeed;
7022  if(Level2OperMode == PreStart)
7023  RouteFlashDuration = 0.0;
7024  else if(PointsChanged)
7025  RouteFlashDuration = AllRoutes->PointsDelay * TempSpeedVal;
7026  else
7027  RouteFlashDuration = AllRoutes->SignalsDelay * TempSpeedVal;
7028  ConstructRoute->SetRouteFlashValues(2, false, false);
7030  }
7031  else
7032  {
7034  }
7035  }
7036  TrainController->BaseTime = TDateTime::CurrentDateTime();
7038  Screen->Cursor = TCursor(-2); // Arrow
7039  }
7040  Utilities->CallLogPop(66);
7041  return;
7042  }
7043  }
7044 
7045  Utilities->CallLogPop(68);
7046  }
7047  catch(const Exception &e)
7048  {
7049  ErrorLog(20, e.Message);
7050  }
7051 }
7052 
7053 // ---------------------------------------------------------------------------
7054 
7055 void TInterface::MainScreenMouseDown3(int Caller, TMouseButton Button, TShiftState Shift, int X, int Y)
7056  // ZoomOut mode
7057 {
7058 // NB: DisplayZoomOutOffsetH & V take account of the Min & Max H & V values so don't need these again
7059  try
7060  {
7061  TrainController->LogEvent("MainScreenMouseDown3," + AnsiString(Button) + "," + AnsiString(X) + "," + AnsiString(Y));
7062  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",MainScreenMouseDown3," + AnsiString(Button) + "," + AnsiString(X) +
7063  "," + AnsiString(Y));
7064  if(Button != mbLeft)
7065  {
7066  // this routine new at v2.1.0. Allows railway moving for zoom-out mode
7069  WholeRailwayMoving = true;
7070  Screen->Cursor = TCursor(-22); // Four arrows;
7071  }
7072  else
7073  {
7074  InfoPanel->Visible = false; // reset infopanel in case not set later
7075  InfoPanel->Caption = "";
7076  int HRounding, VRounding;
7077  int TruePosH = (X / 4) + Display->DisplayZoomOutOffsetH;
7078  int TruePosV = (Y / 4) + Display->DisplayZoomOutOffsetV;
7079  // find nearest screen centre - from 30 to 210 horiz & from 18 to 126 vert
7080  if(TruePosH < 0)
7081  HRounding = -(Utilities->ScreenElementWidth / 4);
7082  else
7083  HRounding = (Utilities->ScreenElementWidth / 4);
7084  int CentreH = (((TruePosH + HRounding) / (Utilities->ScreenElementWidth / 2)) * (Utilities->ScreenElementWidth / 2));
7085  while((CentreH - Track->GetHLocMax()) >= (Utilities->ScreenElementWidth / 2))
7086  CentreH -= (Utilities->ScreenElementWidth / 2);
7087  while((Track->GetHLocMin() - CentreH) >= (Utilities->ScreenElementWidth / 2))
7088  CentreH += (Utilities->ScreenElementWidth / 2);
7089  if(TruePosV < 0)
7090  VRounding = -(Utilities->ScreenElementHeight / 4);
7091  else
7092  VRounding = (Utilities->ScreenElementHeight / 4);
7093  int CentreV = (((TruePosV + VRounding) / (Utilities->ScreenElementHeight / 2)) * (Utilities->ScreenElementHeight / 2));
7094  while((CentreV - Track->GetVLocMax()) >= (Utilities->ScreenElementHeight / 2))
7095  CentreV -= (Utilities->ScreenElementHeight / 2);
7096  while((Track->GetVLocMin() - CentreV) >= (Utilities->ScreenElementHeight / 2))
7097  CentreV += (Utilities->ScreenElementHeight / 2);
7098  Display->DisplayOffsetH = CentreH - (Utilities->ScreenElementWidth / 2);
7100 
7101  TLevel2OperMode TempLevel2OperMode = Level2OperMode;
7102  if(Level1Mode == BaseMode)
7103  SetLevel1Mode(17);
7104  else if(Level1Mode == TrackMode)
7105  {
7106  // set edit menu items
7108  PreventGapOffsetResetting = true; // when return from zoom by clicking screen don't force a return to the
7109  // displayed gap, user wants to display the clicked area
7110  SetLevel2TrackMode(32); // revert to earlier track mode from zoom
7111  PreventGapOffsetResetting = false;
7112  }
7113  else if(Level1Mode == PrefDirMode)
7114  {
7116  SetLevel2PrefDirMode(3); // revert to earlier PrefDir mode from zoom
7117  else
7118  SetLevel1Mode(33); // if PrefDirSelecting revert to normap PrefDirMode
7119  }
7120  // else if(Level1Mode == TrackMode) SetLevel1Mode();//just revert to basic track mode from zoom
7121  // else if(Level1Mode == PrefDirMode) SetLevel1Mode();//just revert to basic PrefDir mode from zoom
7122  else if(Level1Mode == TimetableMode)
7123  {
7124  InfoPanel->Visible = false;
7125  }
7126  // Not OperMode or RestartSessionOperMode as that resets the performance file
7127  else if(TempLevel2OperMode == Operating) // similar to SetLevel2OperMode but without resetting BaseTime
7128  {
7129  OperateButton->Enabled = true;
7130  OperateButton->Glyph->LoadFromResourceName(0, "PauseGraphic");
7131  ExitOperationButton->Enabled = true;
7133  }
7134  else if(TempLevel2OperMode == Paused) // similar to SetLevel2OperMode but without resetting RestartTime
7135  {
7136  OperateButton->Enabled = true;
7137  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
7138  ExitOperationButton->Enabled = true;
7139  TTClockAdjButton->Enabled = true;
7142  }
7143  else if(TempLevel2OperMode == PreStart)
7144  {
7145  OperateButton->Enabled = true;
7146  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
7147  ExitOperationButton->Enabled = true;
7148  TTClockAdjButton->Enabled = true;
7150  }
7151  Display->ZoomOutFlag = false; // reset this after level modes called so gap flash stays set if set to begin with
7154  }
7155  Utilities->CallLogPop(69);
7156  }
7157  catch(const Exception &e)
7158  {
7159  ErrorLog(21, e.Message);
7160  }
7161 }
7162 
7163 // ---------------------------------------------------------------------------
7164 
7165 void __fastcall TInterface::MainScreenMouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
7166 {
7167  try
7168  {
7169  // TrainController->LogEvent("MainScreenMouseMove," + AnsiString(X) + "," + AnsiString(Y)); //dropped at v0.6, too many events
7170  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MainScreenMouseMove," + AnsiString(X) + "," + AnsiString(Y));
7171 
7172  if(!mbLeftDown && WholeRailwayMoving) // new at v2.1.0
7173  {
7174  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
7176  if(X < 0)
7177  X = 0; // ensure pointer stays within display area
7178  if(X > (MainScreen->Width - 1))
7179  X = MainScreen->Width - 1;
7180  if(Y < 0)
7181  Y = 0;
7182  if(Y > (MainScreen->Height - 1))
7183  Y = MainScreen->Height - 1;
7184 
7185  if(!Display->ZoomOutFlag)
7186  {
7187  int StartOffsetX = (X - StartWholeRailwayMoveHPos) % 16;
7188  int StartOffsetY = (Y - StartWholeRailwayMoveVPos) % 16;
7189  if((abs(X - StartWholeRailwayMoveHPos) >= 16) || (abs(Y - StartWholeRailwayMoveVPos) >= 16))
7190  {
7191  int NewH = X - StartWholeRailwayMoveHPos;
7192  int NewV = Y - StartWholeRailwayMoveVPos;
7193  Display->DisplayOffsetH -= NewH / 16;
7194  Display->DisplayOffsetV -= NewV / 16;
7195  StartWholeRailwayMoveHPos = X - StartOffsetX;
7196  StartWholeRailwayMoveVPos = Y - StartOffsetY;
7199  {
7201  }
7202  }
7203  }
7204 
7205  else
7206  {
7207  int StartZOffsetX = (X - StartWholeRailwayMoveHPos) % 4;
7208  int StartZOffsetY = (Y - StartWholeRailwayMoveVPos) % 4;
7209  if((abs(X - StartWholeRailwayMoveHPos) >= 4) || (abs(Y - StartWholeRailwayMoveVPos) >= 4))
7210  {
7211  int NewH = X - StartWholeRailwayMoveHPos;
7212  int NewV = Y - StartWholeRailwayMoveVPos;
7213  Display->DisplayZoomOutOffsetH -= NewH / 4;
7214  Display->DisplayZoomOutOffsetV -= NewV / 4;
7215  StartWholeRailwayMoveHPos = X - StartZOffsetX;
7216  StartWholeRailwayMoveVPos = Y - StartZOffsetY;
7217  Display->ClearDisplay(10);
7219  }
7220  }
7221  TrainController->BaseTime = TDateTime::CurrentDateTime();
7223  }
7224 
7225  else if(mbLeftDown)
7226  {
7228 /* [Repeated from MouseDown] - When 'select' chosen from the Edit menu (only available in 'AddTrack') conditions are set ready to enclose a rectangular screen area
7229  using MouseMove. When MouseDown occurs the starting point is marked (wrt whole railway, not just the screen) and stored in
7230  SelectStartPair. If the mouse button is released and a new start position selected then the earlier one is discarded. Providing the
7231  button is held down subsequent actions occur during MouseMove (to display the changing rectangle) and MouseUp to define the final
7232  selected rectangle.
7233  [New] At this point the select starting position has been defined in SelectStartPair, and the current mouse position is defined (wrt whole
7234  railway) in HLoc & VLoc from the screen positions X & Y by GetTrackLocsFromScreenPos. Both are incremented so that the rectangle
7235  includes the current point (if no mouse movement at all occurs then a 1 x 1 rectangle is displayed). Limits are set to prevent the
7236  displayed rectangle extending off screen. Edges are set at 60 & 36 rather than 59 & 35 because the defined rectangle excludes the
7237  rightmost and bottom HLoc & VLoc values, if 59 & 35 were used the right & bottom screen edges wouldn't be reached. A TRect is then
7238  defined from SelectStartPair and the HLoc/VLoc values, Clearand... called to clear earlier rectangles, and a dashed edge drawn round
7239  the selection.
7240 */
7241  {
7242  TrainController->LogEvent("MouseMove + TrackSelecting");
7243  int CurrentHLoc, CurrentVLoc, StartHLoc = SelectStartPair.first, StartVLoc = SelectStartPair.second;
7244  Track->GetTrackLocsFromScreenPos(2, CurrentHLoc, CurrentVLoc, X, Y);
7245  // to make the rectangle inclusive of the start and current points, need to increase the HLoc value of the
7246  // rightmost point and the VLoc value of the bottommost point
7247  if(CurrentHLoc >= StartHLoc)
7248  CurrentHLoc++;
7249  else
7250  StartHLoc++;
7251  if(CurrentVLoc >= StartVLoc)
7252  CurrentVLoc++;
7253  else
7254  StartVLoc++;
7255  if(CurrentHLoc - Display->DisplayOffsetH > Utilities->ScreenElementWidth)
7257  if(CurrentVLoc - Display->DisplayOffsetV > Utilities->ScreenElementHeight)
7259  if(CurrentHLoc - Display->DisplayOffsetH < 0)
7260  CurrentHLoc = Display->DisplayOffsetH;
7261  if(CurrentVLoc - Display->DisplayOffsetV < 0)
7262  CurrentVLoc = Display->DisplayOffsetV;
7263  TRect TempRect(StartHLoc, StartVLoc, CurrentHLoc, CurrentVLoc);
7264  ClearandRebuildRailway(14); // to clear earlier rectangles
7265  Display->PlotDashedRect(0, TempRect);
7266  Display->Update(); // resurrected when Update() dropped from PlotOutput etc
7267  }
7268 
7270  {
7271  TrainController->LogEvent("MouseMove + PrefDirSelecting");
7272 
7273  int CurrentHLoc, CurrentVLoc, StartHLoc = SelectStartPair.first, StartVLoc = SelectStartPair.second;
7274  Track->GetTrackLocsFromScreenPos(5, CurrentHLoc, CurrentVLoc, X, Y);
7275  // to make the rectangle inclusive of the start and current points, need to increase the HLoc value of the
7276  // rightmost point and the VLoc value of the bottommost point
7277  if(CurrentHLoc >= StartHLoc)
7278  CurrentHLoc++;
7279  else
7280  StartHLoc++;
7281  if(CurrentVLoc >= StartVLoc)
7282  CurrentVLoc++;
7283  else
7284  StartVLoc++;
7285  if(CurrentHLoc - Display->DisplayOffsetH > Utilities->ScreenElementWidth)
7287  if(CurrentVLoc - Display->DisplayOffsetV > Utilities->ScreenElementHeight)
7289  if(CurrentHLoc - Display->DisplayOffsetH < 0)
7290  CurrentHLoc = Display->DisplayOffsetH;
7291  if(CurrentVLoc - Display->DisplayOffsetV < 0)
7292  CurrentVLoc = Display->DisplayOffsetV;
7293  TRect TempRect(StartHLoc, StartVLoc, CurrentHLoc, CurrentVLoc);
7294  ClearandRebuildRailway(57); // to clear earlier rectangles
7295  Display->PlotDashedRect(2, TempRect);
7296  Display->Update(); // need to keep this since Update() not called for PlotSmallOutput as too slow
7297  }
7298 
7300 /* [Repeated from MouseDown] - The same actions apply on MouseDown whether Copy or Cut selected from the menu. First the horizontal and vertical mouse position is
7301  checked and unless it lies within the selected rectangle and not within 4 pixels of an edge the pickup fails and the function returns.
7302  Otherwise flag SelectPickedUp is set to true (to allow it to move during MouseMove and remain in place at MouseUp) and the mouse position
7303  is saved in SelectBitmapMouseLocX & Y for use later in MouseMove & MouseUp.
7304  [New] - The same actions apply on MouseMove whether Copy or Cut selected from the menu. The X & Y mouse positions are checked and set to
7305  stay within the display area. Then the current selection H & V positions are stored in NewSelectBitmapHLoc & VLoc.
7306  These change continually while the mouse and the selection are moving, they are only read on MouseUp to retain the position that it then
7307  occupies. Clearand... is called finally to clear earlier selection displays.
7308 */
7309  {
7310  TrainController->LogEvent("MouseMove + Copy or CutMoving & SelectPickedUp");
7311  if(X < 0)
7312  X = 0; // ensure pointer stays within display area
7313  if(X > (MainScreen->Width - 1))
7314  X = MainScreen->Width - 1;
7315  if(Y < 0)
7316  Y = 0;
7317  if(Y > (MainScreen->Height - 1))
7318  Y = MainScreen->Height - 1;
7321  ClearandRebuildRailway(15); // plots SelectBitmap at the position given by NewSelectBitmapHLoc & ...VLoc
7322  }
7323 
7325  {
7326  TrainController->LogEvent("MouseMove + MoveTextOrGraphic & TextFoundFlag");
7328  NewHPos = TextOrUserGraphicGridVal * (div(NewHPos, TextOrUserGraphicGridVal).quot);
7330  NewVPos = TextOrUserGraphicGridVal * (div(NewVPos, TextOrUserGraphicGridVal).quot);
7331 
7332  TextHandler->TextPtrAt(26, TextItem)->HPos = NewHPos;
7333  TextHandler->TextPtrAt(27, TextItem)->VPos = NewVPos;
7335  }
7336 
7338  {
7339  TrainController->LogEvent("MouseMove + MoveTextOrGraphic & UserGraphicFoundFlag");
7341  NewHPos = TextOrUserGraphicGridVal * (div(NewHPos, TextOrUserGraphicGridVal).quot);
7343  NewVPos = TextOrUserGraphicGridVal * (div(NewVPos, TextOrUserGraphicGridVal).quot);
7344 
7348  }
7349  }
7350  Utilities->CallLogPop(70);
7351  }
7352  catch(const Exception &e)
7353  {
7354  ErrorLog(22, e.Message);
7355  }
7356 }
7357 
7358 // ---------------------------------------------------------------------------
7359 void __fastcall TInterface::MainScreenMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
7360 {
7361 /* [Repeated from MouseDown] - When 'select' chosen from the Edit menu (only available in 'AddTrack') conditions are set ready to enclose a rectangular screen area
7362  using MouseMove. When MouseDown occurs the starting point is marked (wrt whole railway, not just the screen) and stored in
7363  SelectStartPair. If the mouse button is released and a new start position selected then the earlier one is discarded. Providing the
7364  button is held down subsequent actions occur during MouseMove (to display the changing rectangle) and MouseUp to define the final
7365  selected rectangle.
7366  [Repeated from MouseMove] - At this point the select starting position has been defined in SelectStartPair, and the current mouse position is defined (wrt whole
7367  railway) in HLoc & VLoc from the screen positions X & Y by GetTrackLocsFromScreenPos. Both are incremented so that the rectangle
7368  includes the current point (if no mouse movement at all occurs then a 1 x 1 rectangle is displayed). Limits are set to prevent the
7369  displayed rectangle extending off screen. Edges are set at 60 & 36 rather than 59 & 35 because the defined rectangle excludes the
7370  rightmost and bottom HLoc & VLoc values, if 59 & 35 were used the right & bottom screen edges wouldn't be reached. A TRect is then
7371  defined from SelectStartPair and the HLoc/VLoc values, Clearand... called to clear earlier rectangles, and a dashed edge drawn round
7372  the selection.
7373  [New] This function can take some time so an houglass cursor is displayed. The rectangle is fully defined, so the final screen X & Y
7374  values are translated into HLoc & VLoc values (wrt whole railway) and SelectEndPair set using them. The rectangle can be defined in any
7375  direction, so the end points may be before or after the starting points for both horizontal and vertical directions. Therefore the
7376  rectangle that will be used subsequently - SelectRect - is defined from SelectStart and SelectEnd allowing for any direction. Screen
7377  limits are set as during MouseMove, and a dashed edge drawn as before. Then a check is made to see if the final rectangle has any area,
7378  and if not 'Select' mode is kept and the function ends so that a new rectangle can be drawn, otherwise new menu items Cut, Copy & Delete,
7379  are enabled. Now the SelectBitmap is made ready by filling with white prior to the track bitmaps being copied. If this isn't done the
7380  track bitmaps are loaded from the top left hand corner and the rest becomes black - not what is wanted! The SelectVector (defined in
7381  TrackUnit) is then loaded with the elements enclosed by the rectangle, top to bottom and left to right, active track elements first then
7382  inactive track elements. Empty squares are ignored as are default (erased) elements. Now the SelectVector is read and the corresponding
7383  element bitmaps transferred to SelectBitmap in the appropriate positions, then a dashed border added. Finally the cursor is changed back
7384  to an arrow.
7385 */
7386  try
7387  {
7388  TrainController->LogEvent("MainScreenMouseUp," + AnsiString(Button) + "," + AnsiString(X) + "," + AnsiString(Y));
7389  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MainScreenMouseUp," + AnsiString(Button) + "," + AnsiString(X) + "," + AnsiString(Y));
7390  WholeRailwayMoving = false; // added at v2.1.0
7391  Screen->Cursor = TCursor(-2); // Arrow; (to reset from four arrows when moving) added at v2.1.0
7393  {
7394  TrainController->LogEvent("MouseUp + TrackSelecting + mbLeftDown");
7395  Screen->Cursor = TCursor(-11); // Hourglass;
7396  int EndHLoc, EndVLoc, StartHLoc = SelectStartPair.first, StartVLoc = SelectStartPair.second;
7397  Track->GetTrackLocsFromScreenPos(3, EndHLoc, EndVLoc, X, Y); // these values don't allow for offsets so add in later
7398 // to make the rectangle inclusive of the start and current points, need to increase the HLoc value of the
7399 // rightmost point and the VLoc value of the bottommost point
7400  if(EndHLoc >= StartHLoc)
7401  EndHLoc++;
7402  else
7403  StartHLoc++;
7404  if(EndVLoc >= StartVLoc)
7405  EndVLoc++;
7406  else
7407  StartVLoc++;
7408  if(StartHLoc >= EndHLoc)
7409  {
7410  SelectRect.left = EndHLoc;
7411  SelectRect.right = StartHLoc;
7412  }
7413  else
7414  {
7415  SelectRect.left = StartHLoc;
7416  SelectRect.right = EndHLoc;
7417  }
7418  if(StartVLoc >= EndVLoc)
7419  {
7420  SelectRect.top = EndVLoc;
7421  SelectRect.bottom = StartVLoc;
7422  }
7423  else
7424  {
7425  SelectRect.top = StartVLoc;
7426  SelectRect.bottom = EndVLoc;
7427  }
7432  if(SelectRect.left - Display->DisplayOffsetH < 0)
7434  if(SelectRect.top - Display->DisplayOffsetV < 0)
7439  if((SelectRect.top == SelectRect.bottom) || (SelectRect.left == SelectRect.right))
7440  {
7441  SelectionValid = false;
7443  mbLeftDown = false;
7444  Screen->Cursor = TCursor(-2); // Arrow;
7445  Utilities->CallLogPop(71);
7446  return; // no rectangle
7447  }
7448  else
7449  {
7450  ReselectMenuItem->Enabled = false;
7451  CutMenuItem->Enabled = true;
7452  CopyMenuItem->Enabled = true;
7453  FlipMenuItem->Enabled = true;
7454  MirrorMenuItem->Enabled = true;
7455  RotRightMenuItem->Enabled = true;
7456  RotLeftMenuItem->Enabled = true;
7457  RotateMenuItem->Enabled = true;
7458  PasteMenuItem->Enabled = false;
7459 // PasteWithAttributesMenuItem->Enabled = false; //new menu item for v2.2.0 only enabled after cutting
7460  DeleteMenuItem->Enabled = true;
7461  if(Track->IsTrackFinished())
7462  SelectLengthsMenuItem->Enabled = true; // only permit if finished because reverts to DistanceStart
7463  else
7464  SelectLengthsMenuItem->Enabled = false; // and that can only be used if track linked
7465  SelectBiDirPrefDirsMenuItem->Visible = false;
7466  CancelSelectionMenuItem->Enabled = true;
7467  // set SelectBitmap
7468  SelectBitmap->Width = (SelectRect.right - SelectRect.left) * 16;
7469  SelectBitmap->Height = (SelectRect.bottom - SelectRect.top) * 16;
7470 
7471  // fill it with transparent white (i.e. use Draw) else graphics all plot from top left hand corner
7472  for(int H = 0; H < (SelectBitmap->Width) / 16; H++)
7473  {
7474  for(int V = 0; V < (SelectBitmap->Height) / 16; V++)
7475  {
7476  SelectBitmap->Canvas->Draw(H * 16, V * 16, RailGraphics->bmSolidBgnd);
7477  // NB in above if use bmTransparent it ISN'T transparent, but if use the non-transparent bmSolidBgnd it IS transparent
7478  // presumably superimposing a transparent bitmap onto a transparent bitmap makes the result non-transparent!
7479  }
7480  }
7481 
7482  // store elements in Track->SelectVector, active elements first then inactive so active element plotted first during paste
7483  // clear the vector first
7485  TTrackElement TempElement; // default element
7486  bool FoundFlag;
7487  for(int x = SelectRect.left; x < SelectRect.right; x++)
7488  {
7489  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
7490  {
7491  int ATVecPos = Track->GetVectorPositionFromTrackMap(2, x, y, FoundFlag);
7492  if(FoundFlag)
7493  {
7494  TempElement = Track->TrackElementAt(440, ATVecPos);
7495  if(TempElement.SpeedTag > 0)
7496  Track->SelectPush(TempElement); // don't store erase elements
7497  }
7498  }
7499  }
7500  // now store inactive elements
7501  for(int x = SelectRect.left; x < SelectRect.right; x++)
7502  {
7503  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
7504  {
7505  TTrack::TIMPair IATVecPair = Track->GetVectorPositionsFromInactiveTrackMap(2, x, y, FoundFlag);
7506  if(FoundFlag)
7507  {
7508  TempElement = Track->InactiveTrackElementAt(30, IATVecPair.first);
7509  Track->SelectPush(TempElement); // only want SpeedTag & location set, rest defaults
7510  if(IATVecPair.second != IATVecPair.first) // 2 elements stored at location, i.e. platforms
7511  {
7512  TempElement = Track->InactiveTrackElementAt(31, IATVecPair.second);
7513  Track->SelectPush(TempElement);
7514  }
7515  }
7516  }
7517  }
7518  // store text items
7519  int LowSelectHPos = SelectRect.left * 16;
7520  int HighSelectHPos = SelectRect.right * 16;
7521  int LowSelectVPos = SelectRect.top * 16;
7522  int HighSelectVPos = SelectRect.bottom * 16;
7523  TextHandler->SelectTextVector.clear();
7524  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
7525  {
7526  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr < TextHandler->TextVector.end(); TextPtr++)
7527  {
7528  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
7529  HighSelectVPos))
7530  {
7531  // have to create a new TextItem in order to create a new Font object
7532  // BUT: only create new items where they don't appear as named location names
7533  // in SelectVector, since those names shouldn't be copied or pasted.
7534  // NB: altered for PasteWithAttributes - at v2.2.0 save the named element but prefix it with "##**"
7535  // so can paste or not depending on which type of paste is being used (unlikely to use that in a real name)
7536  bool SelectVectorNamedElement = false;
7537  AnsiString SelectTextString; // new at v2.2.0
7538  for(unsigned int x = 0; x < Track->SelectVector.size(); x++)
7539  {
7540  if(Track->SelectVector.at(x).LocationName == TextPtr->TextString)
7541  {
7542  SelectVectorNamedElement = true;
7543  break;
7544  }
7545  }
7546  if(SelectVectorNamedElement) // changed at v2.2.0
7547  {
7548  SelectTextString = "##**" + TextPtr->TextString; // new at v2.2.0
7549  }
7550  else // new at v2.2.0
7551  {
7552  SelectTextString = TextPtr->TextString;
7553  }
7554  TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, SelectTextString, TextPtr->Font);
7555  TextHandler->SelectTextVector.push_back(TextItem); // changed at v2.2.0
7556  }
7557  }
7558  }
7559  // store graphic items, but first clear SelectGraphicVector
7560  Track->SelectGraphicVector.clear();
7561  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
7562  {
7563  for(TTrack::TUserGraphicVector::iterator UserGraphicPtr = Track->UserGraphicVector.begin(); UserGraphicPtr < Track->UserGraphicVector.end();
7564  UserGraphicPtr++)
7565  {
7566  if((UserGraphicPtr->HPos >= LowSelectHPos) && ((UserGraphicPtr->HPos + UserGraphicPtr->Width) < HighSelectHPos) &&
7567  (UserGraphicPtr->VPos >= LowSelectVPos) && ((UserGraphicPtr->VPos + UserGraphicPtr->Height) < HighSelectVPos))
7568  {
7569  Track->SelectGraphicVector.push_back(*UserGraphicPtr);
7570  }
7571  }
7572  }
7573 // new method - direct copying of existing selection so text included
7574  TRect Dest(0, 0, SelectBitmap->Width, SelectBitmap->Height);
7575  TRect Source(((SelectRect.left - Display->DisplayOffsetH) * 16), ((SelectRect.top - Display->DisplayOffsetV) * 16),
7576  ((SelectRect.right - Display->DisplayOffsetH) * 16), ((SelectRect.bottom - Display->DisplayOffsetV) * 16));
7577  SelectBitmap->Canvas->CopyRect(Dest, MainScreen->Canvas, Source);
7578  SelectionValid = true;
7579  }
7580  Screen->Cursor = TCursor(-2); // Arrow;
7581  }
7582 
7584  {
7585  TrainController->LogEvent("MouseUp + PrefDirSelecting + mbLeftDown");
7586  Screen->Cursor = TCursor(-11); // Hourglass;
7587 
7588  int EndHLoc, EndVLoc, StartHLoc = SelectStartPair.first, StartVLoc = SelectStartPair.second;
7589  Track->GetTrackLocsFromScreenPos(6, EndHLoc, EndVLoc, X, Y); // these values don't allow for offsets so add in later
7590 // to make the rectangle inclusive of the start and current points, need to increase the HLoc value of the
7591 // rightmost point and the VLoc value of the bottommost point
7592  if(EndHLoc >= StartHLoc)
7593  EndHLoc++;
7594  else
7595  StartHLoc++;
7596  if(EndVLoc >= StartVLoc)
7597  EndVLoc++;
7598  else
7599  StartVLoc++;
7600  if(StartHLoc >= EndHLoc)
7601  {
7602  SelectRect.left = EndHLoc;
7603  SelectRect.right = StartHLoc;
7604  }
7605  else
7606  {
7607  SelectRect.left = StartHLoc;
7608  SelectRect.right = EndHLoc;
7609  }
7610  if(StartVLoc >= EndVLoc)
7611  {
7612  SelectRect.top = EndVLoc;
7613  SelectRect.bottom = StartVLoc;
7614  }
7615  else
7616  {
7617  SelectRect.top = StartVLoc;
7618  SelectRect.bottom = EndVLoc;
7619  }
7624  if(SelectRect.left - Display->DisplayOffsetH < 0)
7626  if(SelectRect.top - Display->DisplayOffsetV < 0)
7631  if((SelectRect.top == SelectRect.bottom) || (SelectRect.left == SelectRect.right))
7632  {
7634  mbLeftDown = false;
7635  Screen->Cursor = TCursor(-2); // Arrow;
7636  Utilities->CallLogPop(1551);
7637  return; // no rectangle
7638  }
7639  else
7640  {
7641  SelectBiDirPrefDirsMenuItem->Enabled = true;
7642  CancelSelectionMenuItem->Enabled = true;
7643  // don't need SelectBitmap for PrefDir selection
7644 
7645  // store active elements in Track->SelectVector, ignore inactive elements
7646  // clear the vector first
7648  TTrackElement TempElement; // default element
7649  bool FoundFlag;
7650  for(int x = SelectRect.left; x < SelectRect.right; x++)
7651  {
7652  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
7653  {
7654  int ATVecPos = Track->GetVectorPositionFromTrackMap(43, x, y, FoundFlag);
7655  if(FoundFlag)
7656  {
7657  TempElement = Track->TrackElementAt(729, ATVecPos);
7658  if(TempElement.SpeedTag > 0)
7659  Track->SelectPush(TempElement); // don't store erase elements
7660  }
7661  }
7662  }
7663  }
7664  Screen->Cursor = TCursor(-2); // Arrow;
7665  }
7666 
7668 /* [Repeated from MouseDown] - The same actions apply on MouseDown whether Copy or Cut selected from the menu. First the horizontal and vertical mouse position is
7669  checked and unless it lies within the selected rectangle and not within 4 pixels of an edge the pickup fails and the function returns.
7670  Otherwise flag SelectPickedUp is set to true (to allow it to move during MouseMove and remain in place at MouseUp) and the mouse position
7671  is saved in SelectBitmapMouseLocX & Y for use later in MouseMove & MouseUp.
7672  [Repeated from MouseMove] - The same actions apply on MouseMove whether Copy or Cut selected from the menu. The X & Y mouse positions are checked and set to
7673  stay within the display area. Then the current selection H & V positions are stored in NewSelectBitmapHLoc & VLoc.
7674  These change continually while the mouse and the selection are moving, they are only read on MouseUp to retain the position that it then
7675  occupies. Clearand... is called finally to clear earlier selection displays.
7676  [New] - The only action here is to transfer the values of NewSelectBitmapHLoc & VLoc to SelectBitmapHLoc & VLoc so that the selection
7677  stays in the same position (Clearand... checks whether the mouse is moving (both mbLeftDown & SelectPickedUp true) or stopped (either
7678  mbLeftDown or SelectPickedUp false) and uses NewSelectBitmapHLoc & VLoc or SelectBitmapHLoc & SelectBitmapVLoc respectively.
7679 */
7680  {
7681  TrainController->LogEvent("MouseUp + Copy or CutMoving + mbLeftDown + SelectPickedUp");
7684  }
7685 
7686  mbLeftDown = false;
7687  Track->CalcHLocMinEtc(11);
7688  Utilities->CallLogPop(72);
7689  }
7690  catch(const Exception &e)
7691  {
7692  ErrorLog(23, e.Message);
7693  }
7694 }
7695 
7696 // ---------------------------------------------------------------------------
7697 
7698 void __fastcall TInterface::MasterClockTimer(TObject *Sender)
7699 {
7700  try
7701  {
7702  // don't call LogEvent here as would occur too often
7703  // have to allow in zoomout mode
7704  if(ErrorLogCalledFlag)
7705  return; // don't continue after an error
7706 
7707  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MasterClockTimer");
7708  // put counter outside Clock2 as that may be missed
7709  LCResetCounter++;
7710 // this checks LCs every 20 clock ticks (1 sec) & raises barriers if no route & no train present, to avoid delays due to too frequent calls
7711  if(LCResetCounter > 19)
7712  LCResetCounter = 0;
7714  if(WarningFlashCount > 4)
7715  WarningFlashCount = 0;
7716  if(WarningFlashCount == 0)
7717  {
7719  }
7720 
7721  if(Utilities->CallLog.size() > 50) // use CTRL ALT 2 to see CallLogSize as program operates
7722  {
7723  throw Exception("Warning - Utilities->CallLog contains more than 50 items"); // check before clock stopped
7724  }
7725 
7727  // stopped during 'Paused', when modal windows appear - Popup menu & ShowMessage, and at other times
7728  {
7729  // RestartTime is TTClockTime when operation pauses (timetable start time initially),
7730  // BaseTime is CurrentDateTime() when operation restarts
7731 
7732 // clock speed multiplier
7733  double RealTimeDouble = double(TDateTime::CurrentDateTime() - TrainController->BaseTime);
7734  TrainController->TTClockTime = TDateTime(TTClockSpeed * RealTimeDouble) + TrainController->RestartTime;
7735 // TrainController->TTClockTime = TDateTime::CurrentDateTime() - TrainController->BaseTime + TrainController->RestartTime;
7736  }
7737 
7738  TotalTicks++;
7740  {
7741  MissedTicks++;
7742  Utilities->CallLogPop(774);
7743  return;
7744  }
7745  Utilities->Clock2Stopped = true; //don't allow overlapping calls
7746  ClockTimer2(0);
7747  Utilities->Clock2Stopped = false;
7748  Utilities->CallLogPop(73);
7749  }
7750  catch(const Exception &e)
7751  {
7752  ErrorLog(24, e.Message);
7753  }
7754 }
7755 
7756 // ---------------------------------------------------------------------------
7757 
7758 void TInterface::ClockTimer2(int Caller)
7759 {
7760 // called every 50mSec
7761  try
7762  {
7763  // have to allow in zoomout mode
7764  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ClockTimer2");
7765 
7766  // dropped at 2.0.0 because RestoreFocusPanel->SetFocus(); hides the help screen
7767  // If a button holds focus then all that is needed is to click the screen and the arrow keys work correctly
7768 
7769 /* Dropped when new .chm help file introduced at v2.0.0 - this hid it after ~20ms. Replaced by a new section in
7770  MainScreenMouseDown where focus restored to screen when click anywhere on screen, allowing navigation keys to
7771  move screen when clicked if focus had been captured by another panel when these keys just cycle through the panel buttons
7772 
7773  bool FocusRestoreAllowedFlag = true; //added at v1.3.0
7774 
7775  if(TextBox->Focused() || DistanceBox->Focused() || SpeedLimitBox->Focused() || LocationNameTextBox->Focused() || MileEdit->Focused() || ChainEdit->Focused() || YardEdit->Focused() ||
7776  SpeedEditBox2->Focused() || LocationNameComboBox->Focused() || AddSubMinsBox->Focused() || SpeedEditBox->Focused() || PowerEditBox->Focused() || OneEntryTimetableMemo->Focused() ||
7777  AddPrefDirButton->Focused()) //Added at v1.3.0. If any of these has focus then they keep it until they release it. AddPrefDirButton is included as it should keep focus
7778  FocusRestoreAllowedFlag = false; //when it has it - eases the setting of PrefDirs, also this button becomes disabled after use so focus returns to Interface naturally
7779 
7780  if(!Focused() && FocusRestoreAllowedFlag && (GetAsyncKeyState(VK_LBUTTON) >= 0) && (GetAsyncKeyState(VK_RBUTTON) >= 0)) //condition added at v1.3.0 to ensure focus returned to
7781  //Interface (so arrow keys work to move screen) & not left at any of the buttons or other Windows controls
7782  //include the Windows API functions to test that the mouse buttons are not down (strictly only need left but user may have mapped the left onto the right so test both) - if not
7783  //tested then don't always respond to button clicks on navigation and other buttons because the focus can be grabbed back from the button by RestoreFocusPanel before the button
7784  //can respond (takes about 200mSec from click to response) a delay is also included to doubly avoid the button losing focus as above
7785  {
7786  ClockTimer2Count++; //doesn't matter what value it starts at on first use, it will soon revert to 0
7787  if(ClockTimer2Count > 10) ClockTimer2Count = 0; //half second delay
7788  if(ClockTimer2Count == 0)
7789  {
7790  RestoreFocusPanel->Visible = true;
7791  RestoreFocusPanel->Enabled = true;
7792  RestoreFocusPanel->BringToFront();
7793  //RestoreFocusPanel->SetFocus(); //to remove focus from anything else
7794  RestoreFocusPanel->Enabled = false; //to remove focus from RestoreFocusPanel & return it to Interface
7795  RestoreFocusPanel->Visible = false;
7796  }
7797  }
7798  else ClockTimer2Count = 0; //reset to 0 so ensure full delay occurs before RestoreFocusPanel grabs focus from anything else
7799 */
7800 
7801  CallLogTickerLabel->Caption = Utilities->CallLog.size(); // diagnostic test function to ensure all CallLogs are popped - visibility
7802  // toggled by 'Ctrl Alt 2' when Interface form has focus
7803 
7804  // set current time
7805  TDateTime Now = TrainController->TTClockTime;
7806 
7811 
7812  if(OperatorActionPanel->Visible)
7816  TrainController->OpActionPanelHintDelayCounter = 60; // new at v2.2.0
7817 
7818  TrainController->RandomFailureCounter++; // new at v2.4.0 counts up for 53 seconds then resets
7820  {
7822  }
7823 
7824 // Update Displayed Clock - resets to 0 at 96hours
7826 
7827 // Below added at v2.1.0 to ensure WholeRailwayMoving flag reset when not moving (when rh mouse button up) as sometimes misses
7828 // MouseUp events, probably due to a clash between a moving event and a mouse up event. Note that checks that both mouse buttons are up because
7829 // function only checks the physical buttons, not the logical buttons. Most sig bit of return value set form key down.
7830  if(WholeRailwayMoving && (GetAsyncKeyState(VK_LBUTTON) >= 0) && (GetAsyncKeyState(VK_RBUTTON) >= 0))
7831  {
7832  WholeRailwayMoving = false;
7833  Screen->Cursor = TCursor(-2); // Arrow
7834  }
7835 
7836 // save session if required
7837  if(SaveSessionFlag)
7838  {
7839  SaveSession(0);
7840  SaveSessionFlag = false;
7841  }
7842 // load session if required
7843  if(LoadSessionFlag)
7844  {
7845  if(ClearEverything(3))
7846  {
7847  LoadSession(0);
7848  }
7849  LoadSessionFlag = false;
7850  }
7851 
7852 // check if any LCs need barriers raising
7853 
7855  {
7857  {
7858  for(int x = Track->BarriersDownVector.size() - 1; x >= 0; x--) //iterate downwards because erase element
7859  {
7860  bool TrainPresent = false;
7862  TrainPresent)) //returns true for route or train, and TrainPresent true if train on LC
7863  {
7864  if(TrainPresent)
7865  {
7866  Track->BarriersDownVector.at(x).ReducedTimePenalty = true; //to allow 3 mins before time penalty starts to clock up, if no train passes then no time allowance
7867  }
7868  }
7869  else
7870  {
7871  if(Track->BarriersDownVector.at(x).ConsecSignals != 2) //added at v2.6.0 for manual LC operation
7872  {
7873  Track->LCChangeFlag = true;
7875  // check if have exceeded the allowance (3 minutes for a train having passed or 0 for not) and add it to the overall excess time
7876  TDateTime TempExcessLCDownTime;
7877  if(Track->BarriersDownVector.at(x).ReducedTimePenalty)
7878  {
7879  TempExcessLCDownTime = TrainController->TTClockTime - CLC.StartTime - TDateTime(180.0 / 86400);
7880  }
7881  else
7882  {
7883  TempExcessLCDownTime = TrainController->TTClockTime - CLC.StartTime;
7884  }
7885  if(TempExcessLCDownTime > TDateTime(0))
7886  TrainController->ExcessLCDownMins += (double(TempExcessLCDownTime) * 1440);
7887 
7888  CLC.StartTime = TrainController->TTClockTime; // reset these 3 members
7891  Track->SetLinkedLevelCrossingBarrierAttributes(0, CLC.HLoc, CLC.VLoc, 2); // set attr to 2 for changing state
7892  Track->ChangingLCVector.push_back(CLC);
7893  Track->BarriersDownVector.erase(Track->BarriersDownVector.begin() + x);
7894  }
7895  }
7896  }
7897  }
7898  }
7899 // clear LCChangeFlag if no LCs changing
7900  if(Track->ChangingLCVector.empty())
7901  {
7902  Track->LCChangeFlag = false;
7903  }
7904 
7905 // remove any single route elements if operating, but only if not constructing a route, else if extending the single route
7906 // element it may be removed prior to conversion & cause an error
7907 
7908 // note that if a train enters at a continuation and a signal is next but one to the continuation then the route element at that
7909 // signal won't be removed because the train's LagElement is still -1 and trains only remove route elements when LagElement is > -1.
7910 // This also means that a preferred route can't be cancelled as it's under a train, but it's probably not worth adding a patch just for
7911 // this, it shouldn't interfere with operation.
7913  {
7914  bool ElementRemovedFlag = false; // introduced at v0.6 to avoid calling Clearand.... multiple times
7915  for(unsigned int x = 0; x < AllRoutes->AllRoutesSize(); x++)
7916  {
7917  if(AllRoutes->GetFixedRouteAt(187, x).PrefDirSize() == 1)
7918  {
7919  // only allow route element to be removed if not selected for a route start otherwise StartSelectionRouteID will be
7920  // set & will fail at convert
7922  {
7924  //also don't remove if it links two automatic signal routes (reported by Daniel Gill for Darlington via discord on 13/12/20)
7925  //added at v2.6.1
7926  //note that a train will still remove the route element when it reaches it because of the 3rd condition below, but it will be removed when the train
7927  //is half on the preceding element rather than fully on it, in other cases the train has to be fully on the element because the route only becomes a
7928  //single element at that stage
7929  unsigned int LinkFromTVNumber = Track->TrackElementAt(1007, PDE.GetTrackVectorPosition()).Conn[PDE.GetELinkPos()];
7930  unsigned int LinkToTVNumber = Track->TrackElementAt(1008, PDE.GetTrackVectorPosition()).Conn[PDE.GetXLinkPos()];
7931  int RouteNumber1, RouteNumber2, TrainID; //not used
7932  if((AllRoutes->GetRouteTypeAndNumber(37, LinkFromTVNumber, PDE.GetELinkPos(), RouteNumber1) != TAllRoutes::AutoSigsRoute) ||
7933  (AllRoutes->GetRouteTypeAndNumber(38, LinkToTVNumber, PDE.GetXLinkPos(), RouteNumber2) != TAllRoutes::AutoSigsRoute) ||
7934  (Track->TrackElementAt(1009, LinkFromTVNumber).TrainIDOnElement > -1)) //don't need to test for it being a bridge as then LinkFromTVNumber can't be
7935  //an autosigs route
7936  {
7937  AllRoutes->RemoveRouteElement(20, PDE.HLoc, PDE.VLoc, PDE.GetELink());
7938  ElementRemovedFlag = true;
7939  TrainController->LogEvent("SingleRouteElementRemoved, H = " + AnsiString(PDE.HLoc) + ", V = " + AnsiString(PDE.VLoc));
7940  }
7941  }
7942  }
7943  }
7944  if(!Display->ZoomOutFlag && ElementRemovedFlag)
7945  {
7947  }
7948  // if zoomed out ignore, will display correctly when zoom in
7949  // if leave the Zoomout condition out then the zoom out will spontaneously cancel and the track won't display because
7950  // PlotOutput returns if zoomed out, and the zoom out flag isn't reset until the end of Clearand.....
7951  // this was moved outside the for.. next.. loop in v0.6 as it could be called multiple times and slowed down operation (noticeable with a fast clock)
7952  }
7953 // stop clock if hover over a warning
7954  bool WH1 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog1->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog1->Width + OutputLog1->Left))
7955  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog1->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog1->Height + OutputLog1->Top))
7956  && OutputLog1->Caption != "";
7957  bool WH2 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog2->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog2->Width + OutputLog2->Left))
7958  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog2->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog2->Height + OutputLog2->Top))
7959  && OutputLog2->Caption != "";
7960  bool WH3 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog3->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog3->Width + OutputLog3->Left))
7961  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog3->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog3->Height + OutputLog3->Top))
7962  && OutputLog3->Caption != "";
7963  bool WH4 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog4->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog4->Width + OutputLog4->Left))
7964  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog4->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog4->Height + OutputLog4->Top))
7965  && OutputLog4->Caption != "";
7966  bool WH5 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog5->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog5->Width + OutputLog5->Left))
7967  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog5->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog5->Height + OutputLog5->Top))
7968  && OutputLog5->Caption != "";
7969  bool WH6 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog6->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog6->Width + OutputLog6->Left))
7970  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog6->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog6->Height + OutputLog6->Top))
7971  && OutputLog6->Caption != "";
7972  bool WH7 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog7->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog7->Width + OutputLog7->Left))
7973  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog7->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog7->Height + OutputLog7->Top))
7974  && OutputLog7->Caption != "";
7975  bool WH8 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog8->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog8->Width + OutputLog8->Left))
7976  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog8->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog8->Height + OutputLog8->Top))
7977  && OutputLog8->Caption != "";
7978  bool WH9 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog9->Left) && (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog9->Width + OutputLog9->Left))
7979  && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog9->Top) && (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog9->Height + OutputLog9->Top))
7980  && OutputLog9->Caption != "";
7981  bool WH10 = (Mouse->CursorPos.x >= ClientOrigin.x + OutputLog10->Left) &&
7982  (Mouse->CursorPos.x < (ClientOrigin.x + OutputLog10->Width + OutputLog10->Left)) && (Mouse->CursorPos.y >= ClientOrigin.y + OutputLog10->Top) &&
7983  (Mouse->CursorPos.y < (ClientOrigin.y + OutputLog10->Height + OutputLog10->Top)) && OutputLog10->Caption != "";
7984 
7985  if(WH1 || WH2 || WH3 || WH4 || WH5 || WH6 || WH7 || WH8 || WH9 || WH10)
7986  {
7987  if(!WarningHover)
7988  {
7989  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
7991  WarningHover = true;
7992  }
7993  }
7994  else if(WarningHover)
7995  {
7996  WarningHover = false;
7997  TrainController->BaseTime = TDateTime::CurrentDateTime();
7999  }
8000 
8001 // development panel - visibility toggled by 'Ctrl Alt 3' when Interface form has focus
8002  if(DevelopmentPanel->Visible)
8003  {
8004  int Position;
8005  TTrackElement TrackElement;
8006  AnsiString Type[15] =
8007  {"Simple", "Crossover", "Points", "Buffers", "Bridge", "SignalPost", "Continuation", "Platform", "GapJump", "FootCrossing", "Unused", "Concourse",
8008  "Parapet", "NamedNonStationLocation", "Erase"};
8009 
8010  int ScreenX = Mouse->CursorPos.x - MainScreen->ClientOrigin.x;
8011  int ScreenY = Mouse->CursorPos.y - MainScreen->ClientOrigin.y;
8012  int HLoc, VLoc;
8013  AnsiString MouseStr = "Posx: " + AnsiString(ScreenX) + "; Posy: " + AnsiString(ScreenY);
8014  DevelopmentPanel->Caption = CurDir + " " + MouseStr;
8015  Track->GetTrackLocsFromScreenPos(7, HLoc, VLoc, ScreenX, ScreenY);
8016  if(Track->FindNonPlatformMatch(1, HLoc, VLoc, Position, TrackElement))
8017  {
8018  DevelopmentPanel->Caption = MouseStr + "; TVPos: " + AnsiString(Position) + "; H: " + AnsiString(HLoc) + "; V: " + AnsiString(VLoc) +
8019  "; SpTg: " + AnsiString(TrackElement.SpeedTag) + "; Type: " + Type[TrackElement.TrackType] + "; Att: " + AnsiString(TrackElement.Attribute)
8020  + "; TrID: " + AnsiString(TrackElement.TrainIDOnElement) + "; TrID01: " + AnsiString(TrackElement.TrainIDOnBridgeTrackPos01) +
8021  "; TrID23: " + AnsiString(TrackElement.TrainIDOnBridgeTrackPos23) + "; " + TrackElement.LocationName + "; " +
8022  TrackElement.ActiveTrackElementName;
8023 // + "; OAHintCtr: " + TrainController->OpActionPanelHintDelayCounter;
8024  }
8025  }
8026 
8027  if(Level1Mode == TimetableMode)
8028  {
8029 /*These are for Shift Key shortcuts. Unless 'Click()' execution occurs after the key is pressed Windows stores the key until after any code is executed then selects
8030 the timetable entry that begins with the letter corresponding to the key. See DevHistory.txt for the version after v2.4.3 for details.
8031 
8032 First make sure the selected entry is the Highlighted entry, but only if both mouse buttons are up, to make sure AllEntriesTTListBoxMouseUp runs first or TopIndex
8033 likely to be set to the wrong position since when ...Selected... runs it sets TopIndex accordingly. Then when ...MouseUp runs it will use the wrong value and select
8034 the entry that the mouse is now on rather than the one that was chosen.
8035 Later addition: Set member variable AllEntriesTTListBox->TopIndex here if any flag set so when Copy or any other key function runs the top index is correct
8036 */
8037  if((GetKeyState(VK_LBUTTON) >= 0) && (GetKeyState(VK_RBUTTON) >= 0) && (TTCurrentEntryPtr > 0)) //high order bit set to 1 when button down, so arithmetically it is negative
8038  { //TTCurrentEntryPtr == 0 when create a timetable
8039  AllEntriesTTListBox->Selected[TTCurrentEntryPtr - TimetableEditVector.begin()] = true;
8040  }
8041  if(AnyTTKeyFlagSet()) //true if any of the below flags set
8042  {
8043  AllEntriesTTListBox->TopIndex = AllEntriesTTListBoxTopPosition; //reset it to the value before the key press changes it (see FormKeyDown)
8044  }
8046  {
8047  PreviousTTEntryButton->Click();
8048  SetTopIndex(0);
8049  PreviousTTEntryKeyFlag = false;
8050  }
8051  else if(NextTTEntryKeyFlag)
8052  {
8053  NextTTEntryButton->Click();
8054  SetTopIndex(1);
8055  NextTTEntryKeyFlag = false;
8056  }
8057  else if(MoveTTEntryUpKeyFlag)
8058  {
8059  MoveTTEntryUpButton->Click();
8060  SetTopIndex(2);
8061  MoveTTEntryUpKeyFlag = false;
8062  }
8063  else if(MoveTTEntryDownKeyFlag)
8064  {
8065  MoveTTEntryDownButton->Click();
8066  SetTopIndex(3);
8067  MoveTTEntryDownKeyFlag = false;
8068  }
8069  else if(CopyTTEntryKeyFlag)
8070  {
8071  CopyTTEntryButton->Click();
8072  SetTopIndex(4);
8073  CopyTTEntryKeyFlag = false;
8074  }
8075  else if(CutTTEntryKeyFlag)
8076  {
8077  CutTTEntryButton->Click();
8078  SetTopIndex(5);
8079  CutTTEntryKeyFlag = false;
8080  }
8081  else if(PasteTTEntryKeyFlag)
8082  {
8083  PasteTTEntryButton->Click();
8084  SetTopIndex(6);
8085  PasteTTEntryKeyFlag = false;
8086  }
8087  else if(DeleteTTEntryKeyFlag)
8088  {
8089  DeleteTTEntryButton->Click();
8090  SetTopIndex(7);
8091  DeleteTTEntryKeyFlag = false;
8092  }
8093  else if(NewTTEntryKeyFlag)
8094  {
8095  NewTTEntryButton->Click();
8096  SetTopIndex(8);
8097  NewTTEntryKeyFlag = false;
8098  }
8099  else if(AZOrderKeyFlag)
8100  {
8101  AZOrderButton->Click();
8102  SetTopIndex(9);
8103  AZOrderKeyFlag = false;
8104  }
8106  {
8107  TTServiceSyntaxCheckButton->Click();
8108  SetTopIndex(12);
8110  }
8111  else if(ValidateTimetableKeyFlag)
8112  {
8113  ValidateTimetableButton->Click();
8114  SetTopIndex(13);
8115  ValidateTimetableKeyFlag = false;
8116  }
8117  else if(SaveTTKeyFlag)
8118  {
8119  SaveTTButton->Click();
8120  SetTopIndex(14);
8121  SaveTTKeyFlag = false;
8122  }
8123  else if(SaveTTAsKeyFlag)
8124  {
8125  SaveTTAsButton->Click();
8126  SetTopIndex(15);
8127  SaveTTAsKeyFlag = false;
8128  }
8129  else if(RestoreTTKeyFlag)
8130  {
8131  RestoreTTButton->Click();
8132  SetTopIndex(16);
8133  RestoreTTKeyFlag = false;
8134  }
8135  else if(ExportTTKeyFlag)
8136  {
8137  ExportTTButton->Click();
8138  SetTopIndex(17);
8139  ExportTTKeyFlag = false;
8140  }
8141  else if(ConflictAnalysisKeyFlag)
8142  {
8143  ConflictAnalysisButton->Click();
8144  SetTopIndex(18);
8145  ConflictAnalysisKeyFlag = false;
8146  }
8147 
8148 
8149 // highlight timetable entry if in tt mode (have to call this regularly so will scroll with the listbox)
8150  if(!TimetableEditVector.empty() && (TTCurrentEntryPtr > 0))
8151  {
8153  }
8154  else
8155  {
8157  }
8158  }
8159 
8160 // set cursor
8162  {
8163  if(!TempCursorSet)
8164  {
8165  TempCursor = Screen->Cursor;
8166  TempCursorSet = true;
8167  }
8168  Screen->Cursor = TCursor(-11); // Hourglass
8169  }
8170  else
8171  {
8172  if(TempCursorSet)
8173  {
8174  Screen->Cursor = TempCursor;
8175  TempCursorSet = false;
8176  }
8177  }
8178 
8179  if(Level2OperMode == Operating)
8180  {
8181  TrainController->Operate(0); // ensure this called AFTER the single element route removal to ensure any single elements removed
8182  // prior to CallingOnAllowed being called (in UpdateTrain) as that sets a route from the stop signal
8184  {
8185  UpdateOperatorActionPanel(0); // new at v2.2.0 to update panel when train OpTimeToAct updated (updated earlier)
8186  }
8187  TrainController->SignallerTrainRemovedOnAutoSigsRoute = false; // added at v1.3.0 to ensure doesn't persist beyond one call
8188  }
8189 
8190  else if(Level2OperMode == Paused) //added after v2.4.3 to show actions due after a session file reloaded
8191  {
8193  {
8194  for(unsigned int x = 0; x < TrainController->TrainVector.size(); x++)
8195  {
8197  }
8200  }
8201  }
8202 
8203 // plot trains in ZoomOut mode & flash trains where attention needed alternately on & off at each call
8204 // by examining Flash
8205  if((Level1Mode == OperMode) && (Display->ZoomOutFlag))
8206  {
8208  }
8209 
8210 // Deal with any flashing graphics
8212  {
8213  FlashingGraphics(0, Now); // only call when WarningFlash changes
8214  if(Level1Mode == OperMode)
8215  {
8216  if(WarningFlash)
8217  {
8219  {
8220  CrashImage->Visible = true;
8221  }
8223  {
8224  DerailImage->Visible = true;
8225  }
8227  {
8228  SPADImage->Visible = true;
8229  }
8231  {
8232  TrainFailedImage->Visible = true;
8233  }
8235  {
8236  CallOnImage->Visible = true;
8237  }
8239  {
8240  SignalStopImage->Visible = true;
8241  }
8243  {
8244  BufferAttentionImage->Visible = true;
8245  }
8246  }
8247  else
8248  {
8249  CrashImage->Visible = false;
8250  DerailImage->Visible = false;
8251  SPADImage->Visible = false;
8252  TrainFailedImage->Visible = false;
8253  CallOnImage->Visible = false;
8254  SignalStopImage->Visible = false;
8255  BufferAttentionImage->Visible = false;
8256  }
8257  }
8258  else
8259  {
8260  CrashImage->Visible = false;
8261  DerailImage->Visible = false;
8262  SPADImage->Visible = false;
8263  TrainFailedImage->Visible = false;
8264  CallOnImage->Visible = false;
8265  SignalStopImage->Visible = false;
8266  BufferAttentionImage->Visible = false;
8267  }
8268  } // if(WarningFlashCount == 0)
8269  // set buttons etc as appropriate
8271  // if forced route cancellation flag set redisplay to clear the cancelled route
8273  {
8275  AllRoutes->RebuildRailwayFlag = false;
8276  }
8277  // deal with approach locking
8279  // deal with ContinuationAutoSigList
8281  // FloatingLabel function
8282  if((TrackInfoOnOffMenuItem->Caption == "Hide") || (TrainStatusInfoOnOffMenuItem->Caption == "Hide Status") ||
8283  (TrainTTInfoOnOffMenuItem->Caption == "Hide Timetable"))
8284  {
8285  TrackTrainFloat(0);
8286  }
8287  else
8288  {
8289  FloatingPanel->Visible = false;
8290  }
8291  // PerformanceLog check function
8292 /*
8293  if(IsPerformancePanelObscuringFloatingLabel(0) && (ShowPerformancePanel))
8294  {
8295  PerformancePanel->Visible = false;
8296  }
8297  else
8298  {
8299 */
8301  {
8302  PerformancePanel->Visible = true;
8303  }
8304  else
8305  {
8306  PerformancePanel->Visible = false;
8307  }
8308 
8310  {
8311  OperatorActionPanel->Visible = true;
8312  }
8313  else
8314  {
8315  OperatorActionPanel->Visible = false;
8316  }
8317 
8318 // }
8319 
8320  // check if a moving train is present on a route-under-construction start element & cancel it if so
8321  if(RouteMode == RouteContinuing)
8322  {
8323  bool FoundFlag;
8324  int RouteStartVecPos;
8325  if(AutoSigsFlag)
8327  FoundFlag);
8328  else if(ConsecSignalsRoute)
8329  RouteStartVecPos = Track->GetVectorPositionFromTrackMap(8, (SigRouteStartMarker->GetHPos()) / 16, (SigRouteStartMarker->GetVPos()) / 16,
8330  FoundFlag);
8331  else
8333  FoundFlag);
8334  if(FoundFlag && (RouteStartVecPos > -1))
8335  {
8336  TTrackElement TrackElement = Track->TrackElementAt(485, RouteStartVecPos);
8337  if(TrackElement.TrainIDOnElement > -1)
8338  {
8339  if(!(TrainController->TrainVectorAtIdent(2, TrackElement.TrainIDOnElement).Stopped()))
8340  {
8342  // replot train as above erases the front element of the train
8344  }
8345  }
8346  }
8347  }
8348  Utilities->CallLogPop(81);
8349  }
8350  catch(const Exception &e)
8351  {
8352  ErrorLog(25, e.Message);
8353  }
8354 }
8355 
8356 // ---------------------------------------------------------------------------
8357 
8358 void __fastcall TInterface::CallingOnButtonClick(TObject *Sender)
8359 {
8360  try
8361  {
8362  TrainController->LogEvent("CallingOnButtonClick");
8363  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CallingOnButtonClick");
8364  if(CallingOnButton->Down)
8365  {
8366  // CallingOnButton->Down = true;
8367  InfoPanel->Visible = true;
8368  InfoPanel->Caption = "CALLING ON: Select signal for call on";
8369  }
8370  else
8371  {
8372  // CallingOnButton->Down = false;
8374  }
8375  AutoRouteStartMarker->PlotOriginal(29, Display); // if overlay not plotted will ignore
8376  SigRouteStartMarker->PlotOriginal(30, Display); // if overlay not plotted will ignore
8377  NonSigRouteStartMarker->PlotOriginal(31, Display); // if overlay not plotted will ignore
8378  CallingOnButton->Enabled = false;
8379 // added at v1.3.0 to ensure doesn't retain focus - will be re-enabled during ClockTimer2 (in SetSaveMenuAndButtons) if required
8380  Utilities->CallLogPop(82);
8381  }
8382  catch(const Exception &e)
8383  {
8384  ErrorLog(26, e.Message);
8385  }
8386 }
8387 
8388 // ---------------------------------------------------------------------------
8389 void __fastcall TInterface::ScreenLeftButtonClick(TObject *Sender)
8390 {
8391  try
8392  {
8393  // have to allow in zoomout mode
8394  TrainController->LogEvent("ScreenLeftButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8395  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ScreenLeftButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8396  Screen->Cursor = TCursor(-11); // Hourglass;
8397  ScreenLeftButton->Enabled = false; // to make multiple key presses less likely (not entirely successful)
8398  if(!Display->ZoomOutFlag)
8399  {
8400  if(CtrlKey)
8401  {
8402  Display->DisplayOffsetH -= 2;
8403  }
8404  else if(ShiftKey)
8405  {
8407  }
8408  else
8409  {
8411  }
8414  {
8416  }
8417  }
8418  else
8419  {
8420  if(CtrlKey)
8421  {
8423  }
8424  else if(ShiftKey)
8425  {
8427  }
8428  else
8429  {
8431  }
8432  Display->ClearDisplay(0);
8435  Track->PlotSmallRedGap(0);
8436  }
8437  ScreenLeftButton->Enabled = true;
8438  Screen->Cursor = TCursor(-2); // Arrow
8439  Utilities->CallLogPop(83);
8440  }
8441  catch(const Exception &e)
8442  {
8443  ErrorLog(27, e.Message);
8444  }
8445 }
8446 // ---------------------------------------------------------------------------
8447 
8448 void __fastcall TInterface::ScreenRightButtonClick(TObject *Sender)
8449 {
8450  try
8451  {
8452  // have to allow in zoomout mode
8453  TrainController->LogEvent("ScreenRightButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8454  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ScreenRightButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8455  Screen->Cursor = TCursor(-11); // Hourglass;
8456  ScreenRightButton->Enabled = false; // to make multiple key presses less likely (not entirely successful)
8457  if(!Display->ZoomOutFlag)
8458  {
8459  if(CtrlKey)
8460  {
8461  Display->DisplayOffsetH += 2;
8462  }
8463  else if(ShiftKey)
8464  {
8466  }
8467  else
8468  {
8470  }
8473  {
8475  }
8476  }
8477  else
8478  {
8479  if(CtrlKey)
8480  {
8482  }
8483  else if(ShiftKey)
8484  {
8486  }
8487  else
8488  {
8490  }
8491  Display->ClearDisplay(1);
8494  Track->PlotSmallRedGap(1);
8495  }
8496  ScreenRightButton->Enabled = true;
8497  Screen->Cursor = TCursor(-2); // Arrow
8498  Utilities->CallLogPop(84);
8499  }
8500  catch(const Exception &e)
8501  {
8502  ErrorLog(28, e.Message);
8503  }
8504 }
8505 // ---------------------------------------------------------------------------
8506 
8507 void __fastcall TInterface::ScreenDownButtonClick(TObject *Sender)
8508 {
8509  try
8510  {
8511  // have to allow in zoomout mode
8512  TrainController->LogEvent("ScreenDownButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8513  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ScreenDownButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8514  Screen->Cursor = TCursor(-11); // Hourglass;
8515  ScreenDownButton->Enabled = false; // to make multiple key presses less likely (not entirely successful)
8516  // BUT - it does prevent it from retaining focus - so can use the cursor keys to scroll the display without being captured by the buttons
8517  if(!Display->ZoomOutFlag)
8518  {
8519  if(CtrlKey)
8520  {
8521  Display->DisplayOffsetV += 2;
8522  }
8523  else if(ShiftKey)
8524  {
8526  }
8527  else
8528  {
8530  }
8533  {
8535  }
8536  }
8537  else
8538  {
8539  if(CtrlKey)
8540  {
8542  }
8543  else if(ShiftKey)
8544  {
8546  }
8547  else
8548  {
8550  }
8551  Display->ClearDisplay(2);
8554  Track->PlotSmallRedGap(2);
8555  }
8556  ScreenDownButton->Enabled = true;
8557  Screen->Cursor = TCursor(-2); // Arrow
8558  Utilities->CallLogPop(85);
8559  }
8560  catch(const Exception &e)
8561  {
8562  ErrorLog(29, e.Message);
8563  }
8564 }
8565 // ---------------------------------------------------------------------------
8566 
8567 void __fastcall TInterface::ScreenUpButtonClick(TObject *Sender)
8568 {
8569  try
8570  {
8571  // have to allow in zoomout mode
8572  TrainController->LogEvent("ScreenUpButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8573  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ScreenUpButtonClick" + AnsiString((short)ShiftKey) + AnsiString((short)CtrlKey));
8574  Screen->Cursor = TCursor(-11); // Hourglass;
8575  ScreenUpButton->Enabled = false; // to make multiple key presses less likely (not entirely successful)
8576  if(!Display->ZoomOutFlag)
8577  {
8578  if(CtrlKey)
8579  {
8580  Display->DisplayOffsetV -= 2;
8581  }
8582  else if(ShiftKey)
8583  {
8585  }
8586  else
8587  {
8589  }
8592  {
8594  }
8595  }
8596  else
8597  {
8598  if(CtrlKey)
8599  {
8601  }
8602  else if(ShiftKey)
8603  {
8605  }
8606  else
8607  {
8609  }
8610  Display->ClearDisplay(3);
8613  Track->PlotSmallRedGap(3);
8614  }
8615  ScreenUpButton->Enabled = true;
8616  Screen->Cursor = TCursor(-2); // Arrow
8617  Utilities->CallLogPop(86);
8618  }
8619  catch(const Exception &e)
8620  {
8621  ErrorLog(30, e.Message);
8622  }
8623 }
8624 // ---------------------------------------------------------------------------
8625 
8626 void __fastcall TInterface::ZoomButtonClick(TObject *Sender)
8627 {
8628  try
8629  {
8630  // have to allow in zoomout mode
8631  TrainController->LogEvent("ZoomButtonClick");
8632  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ZoomButtonClick");
8633  Screen->Cursor = TCursor(-11); // Hourglass;
8634  ZoomButton->Enabled = false; // this takes focus away so the arrow keys can move the display (v2.0.0)
8635  if(Display->ZoomOutFlag) // i.e resume zoomed in view
8636  {
8637  TrainController->LogEvent("ZoomButtonClick + ZoomOutFlag");
8638 // TLevel2OperMode TempLevel2OperMode = Level2OperMode;
8639  if(Level1Mode == BaseMode)
8640  {
8641  InfoPanel->Visible = false; // reset infopanel in case not set later
8642  InfoPanel->Caption = "";
8643  SetLevel1Mode(18);
8644  }
8645  else if(Level1Mode == TrackMode)
8646  {
8647  InfoPanel->Visible = false; // reset infopanel in case not set later
8648  InfoPanel->Caption = "";
8649  // set edit menu items
8651  SetLevel2TrackMode(33); // revert to earlier track mode from zoom
8652  }
8653  else if(Level1Mode == PrefDirMode)
8654  {
8656  SetLevel1Mode(19); // to redisplay infopanel caption "...select start..."
8657  else
8658  SetLevel2PrefDirMode(4); // revert to PrefDirContinuing PrefDir mode
8659  }
8660 // else if(Level1Mode == TrackMode) SetLevel1Mode();//just revert to basic track mode from zoom
8661 // else if(Level1Mode == PrefDirMode) SetLevel1Mode();//just revert to basic PrefDir mode from zoom
8662  else if(Level1Mode == TimetableMode)
8663  {
8664  InfoPanel->Visible = false;
8665  }
8666  // Don't include OperMode or RestartSessionOperMode as they reset the performance file
8667  else if(Level2OperMode == Operating) // similar to SetLevel2OperMode but without resetting BaseTime
8668  {
8669  OperateButton->Enabled = true;
8670  OperateButton->Glyph->LoadFromResourceName(0, "PauseGraphic");
8671  ExitOperationButton->Enabled = true;
8673  }
8674  else if(Level2OperMode == Paused) // similar to SetLevel2OperMode but without resetting RestartTime
8675  {
8676  OperateButton->Enabled = true;
8677  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
8678  ExitOperationButton->Enabled = true;
8679  TTClockAdjButton->Enabled = true;
8682  }
8683  else if(Level2OperMode == PreStart)
8684  {
8685  OperateButton->Enabled = true;
8686  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
8687  ExitOperationButton->Enabled = true;
8688  TTClockAdjButton->Enabled = true;
8690  }
8691  Display->ZoomOutFlag = false; // reset this after level modes called so gap flash stays set if set to begin with
8693  ClearandRebuildRailway(43); // need to call this after ZoomOutFlag reset to display track, even if Clearand... already called
8694  // earlier during level mode setting - because until ZoomOutFlag reset PlotOutput plots nothing
8695  }
8696  else // set zoomed out view
8697  {
8698  TrainController->LogEvent("ZoomButtonClick + != ZoomOutFlag");
8699  Display->ZoomOutFlag = true;
8701  FileMenu->Enabled = false;
8702  ModeMenu->Enabled = false;
8703  EditMenu->Enabled = false;
8704  TextBox->Visible = false;
8705  LocationNameTextBox->Visible = false;
8706  TTClockAdjButton->Enabled = false;
8707 // DisablePanelsStoreMainMenuStates();//ensure Display->ZoomOutFlag set true before calling
8708  // start assuming normal view is at centre of ZoomOut & calc excesses at each side
8709  int OVOffH_NVCentre = Display->DisplayOffsetH - (1.5 * Utilities->ScreenElementWidth);
8710 // start zoomout centre at DisplayOffsetH + 30 - zoomout width/2 = -(1.5 * 60)
8711  int LeftExcess = OVOffH_NVCentre - Track->GetHLocMin();
8712  int RightExcess = Track->GetHLocMax() - OVOffH_NVCentre - ((4 * Utilities->ScreenElementWidth) - 1);
8713  if((LeftExcess > 0) && (RightExcess > 0))
8714  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre;
8715  else if((LeftExcess > 0) && (RightExcess <= 0))
8716  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre + ((RightExcess) / (Utilities->ScreenElementWidth / 2)) *
8717  (Utilities->ScreenElementWidth / 2); // normalise to nearest screen
8718  else if((LeftExcess <= 0) && (RightExcess > 0))
8719  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre - ((LeftExcess) / (Utilities->ScreenElementWidth / 2)) * (Utilities->ScreenElementWidth / 2);
8720  else
8721  Display->DisplayZoomOutOffsetH = OVOffH_NVCentre; // no excess at either side, so display in centre
8722 
8723  int OVOffV_NVCentre = Display->DisplayOffsetV - (1.5 * Utilities->ScreenElementHeight);
8724  int TopExcess = OVOffV_NVCentre - Track->GetVLocMin();
8725  int BotExcess = Track->GetVLocMax() - OVOffV_NVCentre - ((4 * Utilities->ScreenElementHeight) - 1);
8726  if((TopExcess > 0) && (BotExcess > 0))
8727  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre;
8728  else if((TopExcess > 0) && (BotExcess <= 0))
8729  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre + ((BotExcess) / (Utilities->ScreenElementHeight / 2)) *
8730  (Utilities->ScreenElementHeight / 2); // normalise to nearest half screen
8731  else if((TopExcess <= 0) && (BotExcess > 0))
8732  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre - ((TopExcess) / (Utilities->ScreenElementHeight / 2)) * (Utilities->ScreenElementHeight / 2);
8733  else
8734  Display->DisplayZoomOutOffsetV = OVOffV_NVCentre; // no excess at either side, so display in centre
8735 
8736  Display->ClearDisplay(4);
8740  Track->PlotSmallRedGap(4);
8741  ZoomButton->Glyph->LoadFromResourceName(0, "ZoomIn");
8742  }
8743  Screen->Cursor = TCursor(-2); // Arrow
8744  ZoomButton->Enabled = true; // restore, see above
8745  Utilities->CallLogPop(87);
8746  }
8747  catch(const Exception &e)
8748  {
8749  ErrorLog(31, e.Message);
8750  }
8751 }
8752 // ---------------------------------------------------------------------------
8753 
8754 void __fastcall TInterface::HomeButtonClick(TObject *Sender)
8755 {
8756  try
8757  {
8758  // have to allow in zoomout mode
8759  TrainController->LogEvent("HomeButtonClick");
8760  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",HomeButtonClick");
8761  Screen->Cursor = TCursor(-11); // Hourglass;
8762  HomeButton->Enabled = false; // this takes focus away so the arrow keys can move the display (v2.0.0)
8763  if(!Display->ZoomOutFlag) // zoomed in mode
8764  {
8765  TrainController->LogEvent("HomeButtonClick + zoomed in mode");
8769  {
8771  }
8772  }
8773  else
8774  {
8775  // zoomed out mode
8776  // start assuming normal view is at centre of ZoomOut & calc excesses at each side
8777  TrainController->LogEvent("HomeButtonClick + zoomed out mode");
8779  Display->ClearDisplay(9);
8782  Track->PlotSmallRedGap(5);
8783  }
8784  Screen->Cursor = TCursor(-2); // Arrow
8785  HomeButton->Enabled = true; // restore, see above
8786  Utilities->CallLogPop(88);
8787  }
8788  catch(const Exception &e)
8789  {
8790  ErrorLog(32, e.Message);
8791  }
8792 }
8793 
8794 // ---------------------------------------------------------------------------
8795 void __fastcall TInterface::NewHomeButtonClick(TObject *Sender)
8796 {
8797  try
8798  {
8799  TrainController->LogEvent("NewHomeButtonClick");
8800  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",NewHomeButtonClick");
8801  NewHomeButton->Enabled = false; // this takes focus away so the arrow keys can move the display (v2.0.0)
8802  if(!Display->ZoomOutFlag) // zoomed in mode
8803  {
8806  ResetChangedFileDataAndCaption(23, false); // false because no major changes made
8807  }
8808  else
8809  {
8812  }
8813  Utilities->CallLogPop(1188);
8814  NewHomeButton->Enabled = true; // restore, see above
8815  }
8816  catch(const Exception &e)
8817  {
8818  ErrorLog(174, e.Message);
8819  }
8820 }
8821 
8822 // ---------------------------------------------------------------------------
8823 void __fastcall TInterface::EditMenuClick(TObject *Sender)
8824  // added at v2.1.0 to allow CTRL+X, CTRL+C & CTRL+V in edit menu (see case BaseMode for more information)
8825 {
8826  try
8827  {
8828  CopyMenuItem->ShortCut = TextToShortCut("Ctrl+C");
8829  CutMenuItem->ShortCut = TextToShortCut("Ctrl+X");
8830  PasteMenuItem->ShortCut = TextToShortCut("Ctrl+V");
8831  }
8832  catch(const Exception &e)
8833  {
8834  ErrorLog(196, e.Message);
8835  }
8836 }
8837 
8838 // ---------------------------------------------------------------------------
8839 void __fastcall TInterface::SelectMenuItemClick(TObject *Sender)
8840 {
8841 // draw a rectangle with the left mouse button, enclosing whole 16 x 16 squares
8842  try
8843  {
8844  TrainController->LogEvent("SelectMenuItemClick");
8845  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SelectMenuItemClick");
8846  if(Level1Mode == TrackMode)
8847  {
8848  SelectionValid = false;
8850  SetLevel2TrackMode(34);
8852  {
8853  ShowMessage("Please be aware when pasting that anything inside the pasted area will be overwritten.\n\nThis warning will not be shown again.");
8854  PasteWarningSentFlag = true;
8855  }
8856  }
8857  else if(Level1Mode == PrefDirMode)
8858  {
8861  }
8862  Utilities->CallLogPop(1189);
8863  }
8864  catch(const Exception &e)
8865  {
8866  ErrorLog(145, e.Message);
8867  }
8868 }
8869 
8870 // ---------------------------------------------------------------------------
8871 void __fastcall TInterface::ReselectMenuItemClick(TObject *Sender)
8872 {
8873  try
8874  {
8875  TrainController->LogEvent("ReselectMenuItemClick");
8876  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ReselectMenuItemClick");
8877  if((SelectBitmap->Height == 0) || (SelectBitmap->Width == 0))
8878  {
8879  Utilities->CallLogPop(1424);
8880  return;
8881  }
8882 
8883  int TLHCH = SelectBitmapHLoc;
8884  int TLHCV = SelectBitmapVLoc;
8885  int BRHCH = TLHCH + (SelectBitmap->Width / 16);
8886  int BRHCV = TLHCV + (SelectBitmap->Height / 16);
8887  TRect NewSelectRect(TLHCH, TLHCV, BRHCH, BRHCV);
8888  SelectRect = NewSelectRect;
8890  // set bitmap to reselected area (may be different if flip or mirror had been selected earlier)
8891  TRect Dest(0, 0, SelectBitmap->Width, SelectBitmap->Height);
8892  TRect Source(((SelectRect.left - Display->DisplayOffsetH) * 16), ((SelectRect.top - Display->DisplayOffsetV) * 16),
8893  ((SelectRect.right - Display->DisplayOffsetH) * 16), ((SelectRect.bottom - Display->DisplayOffsetV) * 16));
8894  SelectBitmap->Canvas->CopyRect(Dest, MainScreen->Canvas, Source);
8895 
8896  SelectionValid = true;
8897  ReselectMenuItem->Enabled = false;
8898  CutMenuItem->Enabled = true;
8899  CopyMenuItem->Enabled = true;
8900  FlipMenuItem->Enabled = true;
8901  MirrorMenuItem->Enabled = true;
8902  RotRightMenuItem->Enabled = true;
8903  RotLeftMenuItem->Enabled = true;
8904  RotateMenuItem->Enabled = true;
8905  PasteMenuItem->Enabled = false;
8906  DeleteMenuItem->Enabled = true;
8907  if(Track->IsTrackFinished())
8908  SelectLengthsMenuItem->Enabled = true; // only permit if finished because reverts to DistanceStart
8909  else
8910  SelectLengthsMenuItem->Enabled = false; // and that can only be used if track linked
8911  SelectBiDirPrefDirsMenuItem->Visible = false;
8912  CancelSelectionMenuItem->Enabled = true;
8913  mbLeftDown = false;
8914  // Level1Mode = TrackMode;
8915  // SetLevel1Mode(68);
8917  SetLevel2TrackMode(47);
8918  Utilities->CallLogPop(1425);
8919  }
8920  catch(const Exception &e)
8921  {
8922  ErrorLog(146, e.Message);
8923  }
8924 }
8925 
8926 // ---------------------------------------------------------------------------
8927 void __fastcall TInterface::CutMenuItemClick(TObject *Sender)
8928 {
8929  try
8930  {
8931  TrainController->LogEvent("CutMenuItemClick");
8932  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CutMenuItemClick");
8933  // Level1Mode = TrackMode;
8934  // SetLevel1Mode(69);
8936  SetLevel2TrackMode(35);
8937  Utilities->CallLogPop(1190);
8938  }
8939  catch(const Exception &e)
8940  {
8941  ErrorLog(147, e.Message);
8942  }
8943 }
8944 // ---------------------------------------------------------------------------
8945 
8946 void __fastcall TInterface::CopyMenuItemClick(TObject *Sender)
8947 {
8948  try
8949  {
8950  TrainController->LogEvent("CopyMenuItemClick");
8951  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CopyMenuItemClick");
8952  // Level1Mode = TrackMode;
8953  // SetLevel1Mode(70);
8955  SetLevel2TrackMode(36);
8956  Utilities->CallLogPop(1191);
8957  }
8958  catch(const Exception &e)
8959  {
8960  ErrorLog(148, e.Message);
8961  }
8962 }
8963 
8964 // ---------------------------------------------------------------------------
8965 void __fastcall TInterface::FlipMenuItemClick(TObject *Sender)
8966 {
8967  try
8968  {
8969  TrainController->LogEvent("FlipMenuItemClick");
8970  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",FlipMenuItemClick");
8971  // reset values in SelectVector
8972  int VerSum = SelectRect.top + SelectRect.bottom - 1;
8973  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
8974  {
8975  // Note: (changed again in v2.4.0 to keep attributes) need to change flip, mirror & 180deg functions as only change speedtag without changing anything else.
8976  // This didn't matter before new paste with attributes added at v2.2.0 as a new element was built from the speedtag,
8977  // but now if do a reselect then cut and paste with attributes the wrong graphic is pasted and all other attributes
8978  // are wrong. Need to rebuild a new TrackElement from the new speedtag and use that in the select vector.
8979  // Note that if use Flip, mirror etc then all attributes lost anyway so ok to build a basic element.
8980  int VLoc = VerSum - Track->SelectVectorAt(8, x).VLoc;
8981  int HLoc = Track->SelectVectorAt(7, x).HLoc;
8983  TE.VLoc = VLoc;
8984  TE.HLoc = HLoc;
8985 
8986  TE.ActiveTrackElementName = Track->SelectVectorAt(37, x).ActiveTrackElementName; // these new in v2.4.0 so keeps attributes
8988  TE.Length01 = Track->SelectVectorAt(39, x).Length01;
8989  TE.Length23 = Track->SelectVectorAt(40, x).Length23;
8992  TE.SigAspect = Track->SelectVectorAt(43, x).SigAspect;
8993  Track->SelectVectorAt(26, x) = TE;
8994  }
8995  // reset values in SelectTextVector
8996  for(unsigned int x = 0; x < TextHandler->SelectTextVectorSize(0); x++)
8997  {
8999  // also subtract font height, brings position approximately right
9000  TextItem->VPos = ((VerSum * 16) + 15) - TextItem->VPos - abs(TextItem->Font->Height);
9001  }
9002  // reset values in SelectGraphicVector so the midpoint of the graphic flips about the midline of the selection
9003  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
9004  {
9005  int MidVPosBeforeFlip = Track->SelectGraphicVector.at(x).VPos + (Track->SelectGraphicVector.at(x).Height) / 2;
9006  int MidVPosAfterFlip = ((VerSum * 16) + 15) - MidVPosBeforeFlip;
9007  int TopPosAfterFlip = MidVPosAfterFlip - (Track->SelectGraphicVector.at(x).Height) / 2;
9008  Track->SelectGraphicVector.at(x).VPos = TopPosAfterFlip;
9009  }
9011  SetLevel2TrackMode(48);
9012  Utilities->CallLogPop(1426);
9013  }
9014  catch(const Exception &e)
9015  {
9016  ErrorLog(149, e.Message);
9017  }
9018 }
9019 
9020 // ---------------------------------------------------------------------------
9021 void __fastcall TInterface::MirrorMenuItemClick(TObject *Sender)
9022 {
9023  try
9024  {
9025  TrainController->LogEvent("MirrorMenuItemClick");
9026  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MirrorMenuItemClick");
9027  // reset values in SelectVector
9028  int HorSum = SelectRect.left + SelectRect.right - 1;
9029  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
9030  {
9031  // See note above for FlipMenuItem relating to mods for v2.2.0
9032  int VLoc = Track->SelectVectorAt(22, x).VLoc;
9033  int HLoc = HorSum - Track->SelectVectorAt(6, x).HLoc;
9035  TE.VLoc = VLoc;
9036  TE.HLoc = HLoc;
9037 
9038  TE.ActiveTrackElementName = Track->SelectVectorAt(44, x).ActiveTrackElementName; // these new in v2.4.0 so keeps attributes
9040  TE.Length01 = Track->SelectVectorAt(46, x).Length01;
9041  TE.Length23 = Track->SelectVectorAt(47, x).Length23;
9044  TE.SigAspect = Track->SelectVectorAt(50, x).SigAspect;
9045 
9046 // if(Track->SelectVectorAt(28, x).TrackType == SignalPost) TE.SigAspect = Track->SelectVectorAt(29, x).SigAspect;//TrackType will be the same
9047  Track->SelectVectorAt(30, x) = TE;
9048 // Track->SelectVectorAt(, x).HLoc = HorSum - Track->SelectVectorAt(, x).HLoc;
9049 // Track->SelectVectorAt(, x).SpeedTag = Track->MirrorArray[Track->SelectVectorAt(, x).SpeedTag];
9050  }
9051  // reset values in SelectTextVector
9052  for(unsigned int x = 0; x < TextHandler->SelectTextVectorSize(1); x++)
9053  {
9055  // also subtract half font height for each letter of text, brings position approximately right
9056  TextItem->HPos = ((HorSum * 16) + 15) - TextItem->HPos - (TextItem->TextString.Length() * 0.5 * abs(TextItem->Font->Height));
9057  }
9058  // reset values in SelectGraphicVector so the midpoint of the graphic mirrors about the midline of the selection
9059  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
9060  {
9061  int MidHPosBeforeMirror = Track->SelectGraphicVector.at(x).HPos + (Track->SelectGraphicVector.at(x).Width) / 2;
9062  int MidHPosAfterMirror = ((HorSum * 16) + 15) - MidHPosBeforeMirror;
9063  int LeftPosAfterMirror = MidHPosAfterMirror - (Track->SelectGraphicVector.at(x).Width) / 2;
9064  if(LeftPosAfterMirror < (SelectRect.left * 16)) // shouldn't go below left but check
9065  {
9066  LeftPosAfterMirror = SelectRect.left * 16;
9067  }
9068  Track->SelectGraphicVector.at(x).HPos = LeftPosAfterMirror;
9069  }
9071  SetLevel2TrackMode(49);
9072  Utilities->CallLogPop(1427);
9073  }
9074  catch(const Exception &e)
9075  {
9076  ErrorLog(150, e.Message);
9077  }
9078 }
9079 
9080 // ---------------------------------------------------------------------------
9081 void __fastcall TInterface::RotateMenuItemClick(TObject *Sender)
9082 {
9083  try
9084  {
9085  TrainController->LogEvent("Rotate180MenuItemClick");
9086  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",Rotate180MenuItemClick");
9087  // reset values in SelectVector
9088  int HorSum = SelectRect.left + SelectRect.right - 1;
9089  int VerSum = SelectRect.top + SelectRect.bottom - 1;
9090  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
9091  {
9092  // See note above for FlipMenuItem relating to mods for v2.2.0
9093  int VLoc = VerSum - Track->SelectVectorAt(23, x).VLoc;
9094  int HLoc = HorSum - Track->SelectVectorAt(36, x).HLoc;
9096  TE.VLoc = VLoc;
9097  TE.HLoc = HLoc;
9098 
9099  TE.ActiveTrackElementName = Track->SelectVectorAt(51, x).ActiveTrackElementName; // these new in v2.4.0 so keeps attributes
9101  TE.Length01 = Track->SelectVectorAt(53, x).Length01;
9102  TE.Length23 = Track->SelectVectorAt(54, x).Length23;
9105  TE.SigAspect = Track->SelectVectorAt(57, x).SigAspect;
9106 
9107 // if(Track->SelectVectorAt(32, x).TrackType == SignalPost) TE.SigAspect = Track->SelectVectorAt(33, x).SigAspect; dropped in v2.4.0 for above
9108  Track->SelectVectorAt(34, x) = TE;
9109 // TTrackElement &TempEl = Track->SelectVectorAt(13, x);
9110 // TempEl.HLoc = HorSum - TempEl.HLoc;
9111 // TempEl.VLoc = VerSum - TempEl.VLoc;
9112 // TempEl.SpeedTag = Track->MirrorArray[Track->FlipArray[TempEl.SpeedTag]];
9113  }
9114  // reset values in SelectTextVector
9115  for(unsigned int x = 0; x < TextHandler->SelectTextVectorSize(2); x++)
9116  {
9118  // also subtract half font height for each letter of text, brings position approximately right horizontally
9119  TextItem->HPos = ((HorSum * 16) + 15) - TextItem->HPos - (TextItem->TextString.Length() * 0.5 * abs(TextItem->Font->Height));
9120  // also subtract font height, brings position approximately right vertically
9121  TextItem->VPos = ((VerSum * 16) + 15) - TextItem->VPos - abs(TextItem->Font->Height);
9122  }
9123  // reset flip values in SelectGraphicVector so the midpoint of the graphic flips about the midline of the selection
9124  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
9125  {
9126  int MidVPosBeforeFlip = Track->SelectGraphicVector.at(x).VPos + (Track->SelectGraphicVector.at(x).Height) / 2;
9127  int MidVPosAfterFlip = ((VerSum * 16) + 15) - MidVPosBeforeFlip;
9128  int TopPosAfterFlip = MidVPosAfterFlip - (Track->SelectGraphicVector.at(x).Height) / 2;
9129  if(TopPosAfterFlip < (SelectRect.top * 16)) // shouldn't go above top but check
9130  {
9131  TopPosAfterFlip = SelectRect.top * 16;
9132  }
9133  Track->SelectGraphicVector.at(x).VPos = TopPosAfterFlip;
9134  }
9135  // reset mirror in SelectGraphicVector so the midpoint of the graphic mirrors about the midline of the selection
9136  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
9137  {
9138  int MidHPosBeforeMirror = Track->SelectGraphicVector.at(x).HPos + (Track->SelectGraphicVector.at(x).Width) / 2;
9139  int MidHPosAfterMirror = ((HorSum * 16) + 15) - MidHPosBeforeMirror;
9140  int LeftPosAfterMirror = MidHPosAfterMirror - (Track->SelectGraphicVector.at(x).Width) / 2;
9141  if(LeftPosAfterMirror < (SelectRect.left * 16)) // shouldn't go below left but check
9142  {
9143  LeftPosAfterMirror = SelectRect.left * 16;
9144  }
9145  Track->SelectGraphicVector.at(x).HPos = LeftPosAfterMirror;
9146  }
9147  // Level1Mode = TrackMode;
9148  // SetLevel1Mode(73);
9150  SetLevel2TrackMode(50);
9151  Utilities->CallLogPop(1435);
9152  }
9153  catch(const Exception &e)
9154  {
9155  ErrorLog(151, e.Message);
9156  }
9157 }
9158 // ---------------------------------------------------------------------------
9159 
9160 void __fastcall TInterface::RotRightMenuItemClick(TObject *Sender)
9161 {
9162  try
9163  {
9164  TrainController->LogEvent("RotateRight90MenuItemClick");
9165  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RotateRight90MenuItemClick");
9166  Screen->Cursor = TCursor(-11); // Hourglass
9167  // check first if a square and if not give message & quit
9168  if((SelectRect.right - SelectRect.left) != (SelectRect.bottom - SelectRect.top))
9169  {
9170  // use left vertical side to make square & keep top lh corner unless rhs would exceed display, in which case use the right vertical & keep to rh corner
9171  int VertSize = SelectRect.bottom - SelectRect.top;
9172  if((SelectRect.Left + VertSize - Display->DisplayOffsetH) > Utilities->ScreenElementWidth)
9173  {
9174  // use right hand vertical & make square to left of that
9175  SelectRect.left = SelectRect.right - VertSize;
9176  }
9177  else
9178  {
9179  SelectRect.right = SelectRect.left + VertSize;
9180  }
9183  int button = Application->MessageBox
9184  (L"Original selection adjusted to make it square. 'OK' to keep this selection or 'Cancel' to make a new selection",
9185  L"Left click and hold here to move this message box", MB_OKCANCEL);
9186  if(button == IDCANCEL)
9187  {
9188  ResetSelectRect();
9189  Level1Mode = TrackMode; // call this first to clear everything, then set PrefDir mode
9190  SetLevel1Mode(133);
9192  SetLevel2TrackMode(59);
9194  Screen->Cursor = TCursor(-2); // Arrow
9195  Utilities->CallLogPop(2121);
9196  return;
9197  }
9198  }
9199  // set SelectBitmap (only need the dimensions here as not moving the selection)
9202  SelectBitmap->Width = (SelectRect.right - SelectRect.left) * 16;
9203  SelectBitmap->Height = (SelectRect.bottom - SelectRect.top) * 16;
9204  // store track elements and text in select vectors
9206  TTrackElement TempElement; // default element
9207  bool FoundFlag;
9208  for(int x = SelectRect.left; x < SelectRect.right; x++)
9209  {
9210  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
9211  {
9212  int ATVecPos = Track->GetVectorPositionFromTrackMap(57, x, y, FoundFlag);
9213  if(FoundFlag)
9214  {
9215  TempElement = Track->TrackElementAt(959, ATVecPos);
9216  if(TempElement.SpeedTag > 0)
9217  Track->SelectPush(TempElement);
9218  }
9219  }
9220  }
9221  // now store inactive elements
9222  for(int x = SelectRect.left; x < SelectRect.right; x++)
9223  {
9224  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
9225  {
9226  TTrack::TIMPair IATVecPair = Track->GetVectorPositionsFromInactiveTrackMap(28, x, y, FoundFlag);
9227  if(FoundFlag)
9228  {
9229  TempElement = Track->InactiveTrackElementAt(126, IATVecPair.first);
9230  Track->SelectPush(TempElement); // only want SpeedTag & location set, rest defaults
9231  if(IATVecPair.second != IATVecPair.first) // 2 elements stored at location, i.e. platforms
9232  {
9233  TempElement = Track->InactiveTrackElementAt(127, IATVecPair.second);
9234  Track->SelectPush(TempElement);
9235  }
9236  }
9237  }
9238  }
9239  // store text items
9240  int LowSelectHPos = SelectRect.left * 16;
9241  int HighSelectHPos = SelectRect.right * 16;
9242  int LowSelectVPos = SelectRect.top * 16;
9243  int HighSelectVPos = SelectRect.bottom * 16;
9244  TextHandler->SelectTextVector.clear();
9245  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
9246  {
9247  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr < TextHandler->TextVector.end(); TextPtr++)
9248  {
9249  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos < HighSelectVPos))
9250  {
9251  // have to create a new TextItem in order to create a new Font object
9252  // BUT: only create new items where they don't appear as named location names
9253  // in SelectVector, since those names shouldn't be copied or pasted.
9254  // NB: altered for PasteWithAttributes - at v2.2.0 save the named element but prefix it with "##**"
9255  // so can paste or not depending on which type of paste is being used (unlikely to use that in a real name)
9256  bool SelectVectorNamedElement = false;
9257  AnsiString SelectTextString; // new at v2.2.0
9258  for(unsigned int x = 0; x < Track->SelectVector.size(); x++)
9259  {
9260  if(Track->SelectVector.at(x).LocationName == TextPtr->TextString)
9261  {
9262  SelectVectorNamedElement = true;
9263  break;
9264  }
9265  }
9266  if(SelectVectorNamedElement) // changed at v2.2.0
9267  {
9268  SelectTextString = "##**" + TextPtr->TextString; // new at v2.2.0
9269  }
9270  else // new at v2.2.0
9271  {
9272  SelectTextString = TextPtr->TextString;
9273  }
9274  TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, SelectTextString, TextPtr->Font);
9275  TextHandler->SelectTextVector.push_back(TextItem); // changed at v2.2.0
9276  }
9277  }
9278  }
9279  // store graphic items, but first clear SelectGraphicVector
9280  Track->SelectGraphicVector.clear();
9281  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
9282  {
9283  for(TTrack::TUserGraphicVector::iterator UserGraphicPtr = Track->UserGraphicVector.begin(); UserGraphicPtr < Track->UserGraphicVector.end();
9284  UserGraphicPtr++)
9285  {
9286  if((UserGraphicPtr->HPos >= LowSelectHPos) && ((UserGraphicPtr->HPos + UserGraphicPtr->Width) < HighSelectHPos) && (UserGraphicPtr->VPos >=
9287  LowSelectVPos) && ((UserGraphicPtr->VPos + UserGraphicPtr->Height) < HighSelectVPos))
9288  {
9289  Track->SelectGraphicVector.push_back(*UserGraphicPtr);
9290  }
9291  }
9292  }
9293  // now transform the H & V for rh rotate
9294  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
9295  {
9296  int HLoc = SelectRect.bottom - 1 + SelectRect.left - Track->SelectVectorAt(74, x).VLoc;
9297  int VLoc = SelectRect.top - SelectRect.left + Track->SelectVectorAt(75, x).HLoc;
9299  TE.VLoc = VLoc;
9300  TE.HLoc = HLoc;
9301 
9302  TE.ActiveTrackElementName = Track->SelectVectorAt(58, x).ActiveTrackElementName; // these new in v2.4.0 so keeps attributes
9304  TE.Length01 = Track->SelectVectorAt(60, x).Length01;
9305  TE.Length23 = Track->SelectVectorAt(61, x).Length23;
9308  TE.SigAspect = Track->SelectVectorAt(64, x).SigAspect;
9309  Track->SelectVectorAt(65, x) = TE;
9310  }
9311  // reset values in SelectTextVector
9312  for(unsigned int x = 0; x < TextHandler->SelectTextVectorSize(3); x++)
9313  {
9314 // no point trying to locate text properly as it stays horizontal so will always be wrongly placed, just list all itels vertically at lhs
9315 // & if a lot then some will extend beyond the selection
9317  // also subtract half font height for each letter of text, brings position approximately right horizontally
9318  TextItem->HPos = (SelectRect.left) * 16;
9319  TextItem->VPos = (SelectRect.top + x) * 16;
9320  }
9321  // reset values in SelectGraphicVector
9322  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
9323  {
9324  int MidHPosBeforeRotate = Track->SelectGraphicVector.at(x).HPos + Track->SelectGraphicVector.at(x).Width / 2;
9325  int MidVPosBeforeRotate = Track->SelectGraphicVector.at(x).VPos + Track->SelectGraphicVector.at(x).Height / 2;
9326  int MidHPosAfterRotate = ((SelectRect.bottom * 16) - 1) + (SelectRect.left * 16) - MidVPosBeforeRotate;
9327  int MidVPosAfterRotate = ((SelectRect.top - SelectRect.left) * 16) + MidHPosBeforeRotate;
9328  int LeftPosAfterRotate = MidHPosAfterRotate - (Track->SelectGraphicVector.at(x).Width) / 2;
9329  int TopPosAfterRotate = MidVPosAfterRotate - (Track->SelectGraphicVector.at(x).Height) / 2;
9330  Track->SelectGraphicVector.at(x).HPos = LeftPosAfterRotate;
9331  Track->SelectGraphicVector.at(x).VPos = TopPosAfterRotate;
9332  }
9333  Screen->Cursor = TCursor(-2); // Arrow
9335  SetLevel2TrackMode(60);
9336  Utilities->CallLogPop(2122);
9337  }
9338  catch(const Exception &e)
9339  {
9340  ErrorLog(205, e.Message);
9341  }
9342 }
9343 
9344 // ---------------------------------------------------------------------------
9345 
9346 void __fastcall TInterface::RotLeftMenuItemClick(TObject *Sender)
9347 {
9348  try
9349  {
9350  TrainController->LogEvent("RotateLeft90MenuItemClick");
9351  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RotateLeft90MenuItemClick");
9352  Screen->Cursor = TCursor(-11); // Hourglass;
9353  // check first if a square and if not give message & quit
9354  if((SelectRect.right - SelectRect.left) != (SelectRect.bottom - SelectRect.top))
9355  {
9356  // use left vertical side to make square & keep top lh corner unless rhs would exceed display, in which case use the right vertical & keep to rh corner
9357  int VertSize = SelectRect.bottom - SelectRect.top;
9358  if((SelectRect.Left + VertSize - Display->DisplayOffsetH) > Utilities->ScreenElementWidth)
9359  {
9360  // use right hand vertical & make square to left of that
9361  SelectRect.left = SelectRect.right - VertSize;
9362  }
9363  else
9364  {
9365  SelectRect.right = SelectRect.left + VertSize;
9366  }
9369  int button = Application->MessageBox
9370  (L"Original selection adjusted to make it square. 'OK' to keep this selection or 'Cancel' to make a new selection",
9371  L"Left click and hold here to move this message box", MB_OKCANCEL);
9372  if(button == IDCANCEL)
9373  {
9374  ResetSelectRect();
9375  Level1Mode = TrackMode; // call this first to clear everything, then set PrefDir mode
9376  SetLevel1Mode(134);
9378  SetLevel2TrackMode(61);
9380  Screen->Cursor = TCursor(-2); // Arrow
9381  Utilities->CallLogPop(2123);
9382  return;
9383  }
9384  }
9385  // set SelectBitmap (only need the dimensions here as not moving the selection)
9388  SelectBitmap->Width = (SelectRect.right - SelectRect.left) * 16;
9389  SelectBitmap->Height = (SelectRect.bottom - SelectRect.top) * 16;
9390  // store track elements and text in select vectors
9392  TTrackElement TempElement; // default element
9393  bool FoundFlag;
9394  for(int x = SelectRect.left; x < SelectRect.right; x++)
9395  {
9396  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
9397  {
9398  int ATVecPos = Track->GetVectorPositionFromTrackMap(58, x, y, FoundFlag);
9399  if(FoundFlag)
9400  {
9401  TempElement = Track->TrackElementAt(960, ATVecPos);
9402  if(TempElement.SpeedTag > 0)
9403  Track->SelectPush(TempElement);
9404  }
9405  }
9406  }
9407  // now store inactive elements
9408  for(int x = SelectRect.left; x < SelectRect.right; x++)
9409  {
9410  for(int y = SelectRect.top; y < SelectRect.bottom; y++)
9411  {
9412  TTrack::TIMPair IATVecPair = Track->GetVectorPositionsFromInactiveTrackMap(29, x, y, FoundFlag);
9413  if(FoundFlag)
9414  {
9415  TempElement = Track->InactiveTrackElementAt(128, IATVecPair.first);
9416  Track->SelectPush(TempElement); // only want SpeedTag & location set, rest defaults
9417  if(IATVecPair.second != IATVecPair.first) // 2 elements stored at location, i.e. platforms
9418  {
9419  TempElement = Track->InactiveTrackElementAt(129, IATVecPair.second);
9420  Track->SelectPush(TempElement);
9421  }
9422  }
9423  }
9424  }
9425  // store text items
9426  int LowSelectHPos = SelectRect.left * 16;
9427  int HighSelectHPos = SelectRect.right * 16;
9428  int LowSelectVPos = SelectRect.top * 16;
9429  int HighSelectVPos = SelectRect.bottom * 16;
9430  TextHandler->SelectTextVector.clear();
9431  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
9432  {
9433  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->TextVector.begin(); TextPtr < TextHandler->TextVector.end(); TextPtr++)
9434  {
9435  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos < HighSelectVPos))
9436  {
9437  // have to create a new TextItem in order to create a new Font object
9438  // BUT: only create new items where they don't appear as named location names
9439  // in SelectVector, since those names shouldn't be copied or pasted.
9440  // NB: altered for PasteWithAttributes - at v2.2.0 save the named element but prefix it with "##**"
9441  // so can paste or not depending on which type of paste is being used (unlikely to use that in a real name)
9442  bool SelectVectorNamedElement = false;
9443  AnsiString SelectTextString; // new at v2.2.0
9444  for(unsigned int x = 0; x < Track->SelectVector.size(); x++)
9445  {
9446  if(Track->SelectVector.at(x).LocationName == TextPtr->TextString)
9447  {
9448  SelectVectorNamedElement = true;
9449  break;
9450  }
9451  }
9452  if(SelectVectorNamedElement) // changed at v2.2.0
9453  {
9454  SelectTextString = "##**" + TextPtr->TextString; // new at v2.2.0
9455  }
9456  else // new at v2.2.0
9457  {
9458  SelectTextString = TextPtr->TextString;
9459  }
9460  TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, SelectTextString, TextPtr->Font);
9461  TextHandler->SelectTextVector.push_back(TextItem); // changed at v2.2.0
9462  }
9463  }
9464  }
9465  // store graphic items, but first clear SelectGraphicVector
9466  Track->SelectGraphicVector.clear();
9467  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
9468  {
9469  for(TTrack::TUserGraphicVector::iterator UserGraphicPtr = Track->UserGraphicVector.begin(); UserGraphicPtr < Track->UserGraphicVector.end();
9470  UserGraphicPtr++)
9471  {
9472  if((UserGraphicPtr->HPos >= LowSelectHPos) && ((UserGraphicPtr->HPos + UserGraphicPtr->Width) < HighSelectHPos) && (UserGraphicPtr->VPos >=
9473  LowSelectVPos) && ((UserGraphicPtr->VPos + UserGraphicPtr->Height) < HighSelectVPos))
9474  {
9475  Track->SelectGraphicVector.push_back(*UserGraphicPtr);
9476  }
9477  }
9478  }
9479  // now transform the H & V for lh rotate
9480  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
9481  {
9482  int HLoc = SelectRect.left - SelectRect.top + Track->SelectVectorAt(76, x).VLoc;
9483  int VLoc = SelectRect.bottom - 1 + SelectRect.left - Track->SelectVectorAt(77, x).HLoc;
9485  TE.VLoc = VLoc;
9486  TE.HLoc = HLoc;
9487 
9488  TE.ActiveTrackElementName = Track->SelectVectorAt(66, x).ActiveTrackElementName; // these new in v2.4.0 so keeps attributes
9490  TE.Length01 = Track->SelectVectorAt(68, x).Length01;
9491  TE.Length23 = Track->SelectVectorAt(69, x).Length23;
9494  TE.SigAspect = Track->SelectVectorAt(72, x).SigAspect;
9495  Track->SelectVectorAt(73, x) = TE;
9496  }
9497  // reset values in SelectTextVector
9498  for(unsigned int x = 0; x < TextHandler->SelectTextVectorSize(4); x++)
9499  {
9500 // no point trying to locate text properly as it stays horizontal so will always be wrongly placed, just list all itels vertically at lhs
9501 // & if a lot then some will extend beyond the selection
9503  // also subtract half font height for each letter of text, brings position approximately right horizontally
9504  TextItem->HPos = (SelectRect.left) * 16;
9505  TextItem->VPos = (SelectRect.top + x) * 16;
9506  }
9507  // reset values in SelectGraphicVector
9508  for(unsigned int x = 0; x < Track->SelectGraphicVector.size(); x++)
9509  {
9510  int MidHPosBeforeRotate = Track->SelectGraphicVector.at(x).HPos + Track->SelectGraphicVector.at(x).Width / 2;
9511  int MidVPosBeforeRotate = Track->SelectGraphicVector.at(x).VPos + Track->SelectGraphicVector.at(x).Height / 2;
9512  int MidHPosAfterRotate = ((SelectRect.left - SelectRect.top) * 16) + MidVPosBeforeRotate;
9513  int MidVPosAfterRotate = ((SelectRect.bottom * 16) - 1) + (SelectRect.left * 16) - MidHPosBeforeRotate;
9514  int LeftPosAfterRotate = MidHPosAfterRotate - (Track->SelectGraphicVector.at(x).Width) / 2;
9515  int TopPosAfterRotate = MidVPosAfterRotate - (Track->SelectGraphicVector.at(x).Height) / 2;
9516  Track->SelectGraphicVector.at(x).HPos = LeftPosAfterRotate;
9517  Track->SelectGraphicVector.at(x).VPos = TopPosAfterRotate;
9518  }
9519  Screen->Cursor = TCursor(-2); // Arrow
9521  SetLevel2TrackMode(62);
9522  Utilities->CallLogPop(2124);
9523  }
9524  catch(const Exception &e)
9525  {
9526  ErrorLog(206, e.Message);
9527  }
9528 }
9529 
9530 // ---------------------------------------------------------------------------
9531 
9532 void __fastcall TInterface::PasteMenuItemClick(TObject *Sender)
9533 {
9534  try
9535  {
9536  TrainController->LogEvent("PasteMenuItemClick");
9537  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PasteMenuItemClick");
9538  // Level1Mode = TrackMode;
9539  // SetLevel1Mode(74);
9541  SetLevel2TrackMode(58);
9542  Utilities->CallLogPop(2060);
9543  }
9544  catch(const Exception &e)
9545  {
9546  ErrorLog(198, e.Message);
9547  }
9548 }
9549 
9550 // ---------------------------------------------------------------------------
9551 void __fastcall TInterface::DeleteMenuItemClick(TObject *Sender)
9552 {
9553  try
9554  {
9555  TrainController->LogEvent("DeleteMenuItemClick");
9556  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",DeleteMenuItemClick");
9557  // Level1Mode = TrackMode;
9558  // SetLevel1Mode(75);
9560  SetLevel2TrackMode(38);
9561  Utilities->CallLogPop(1193);
9562  }
9563  catch(const Exception &e)
9564  {
9565  ErrorLog(153, e.Message);
9566  }
9567 }
9568 // ---------------------------------------------------------------------------
9569 
9570 void __fastcall TInterface::SelectLengthsMenuItemClick(TObject *Sender)
9571 {
9572  try
9573  {
9574  TrainController->LogEvent("SelectLengthsMenuItemClick");
9575  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SelectLengthsMenuItemClick");
9576  TrackElementPanel->Visible = false;
9577  TrackLengthPanel->Visible = true;
9578  TrackLengthPanel->SetFocus();
9579  SelectLengthsFlag = true;
9580  InfoPanel->Visible = true;
9581  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Set values or leave blank for no change";
9583  {
9584  ShowMessage("Note: length value will apply to each element's track within the selection.\n\nThis message will not be shown again.");
9585  LengthWarningSentFlag = true;
9586  }
9587  DistanceBox->Text = "";
9588  SpeedLimitBox->Text = "";
9591  ResetChangedFileDataAndCaption(19, true); // true for NonPrefDirChangesMade
9592  Utilities->CallLogPop(1414);
9593  }
9594  catch(const Exception &e)
9595  {
9596  ErrorLog(154, e.Message);
9597  }
9598 }
9599 
9600 // ---------------------------------------------------------------------------
9601 
9602 void __fastcall TInterface::SelectBiDirPrefDirsMenuItemClick(TObject *Sender)
9603 {
9604 /* SelectVector contains all the track elements (and inactive elements but don't need them), so create up to 4 PrefDir
9605  elements from each one, and add each into ConstructPrefDir, then when all added use ConsolidatePrefDirs to add to EveryPrefDir
9606 */
9607  try
9608  {
9609  TrainController->LogEvent("SelectBiDirPrefDirsMenuItemClick");
9610  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SelectBiDirPrefDirsMenuItemClick");
9612  bool FoundFlag = false;
9613  if(Track->SelectVector.empty())
9614  {
9615  Utilities->CallLogPop(1550);
9616  return;
9617  }
9618  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
9619  {
9620  TTrackElement TE = Track->SelectVectorAt(14, x);
9621  int VecPos = Track->GetVectorPositionFromTrackMap(42, TE.HLoc, TE.VLoc, FoundFlag);
9622  if(FoundFlag)
9623  {
9624  if((TE.TrackType == Points) || (TE.TrackType == Bridge) || (TE.TrackType == Crossover)) // 2-track element
9625  {
9626  TPrefDirElement PE0(TE, TE.Link[0], 0, TE.Link[1], 1, VecPos);
9628  TPrefDirElement PE1(TE, TE.Link[1], 1, TE.Link[0], 0, VecPos);
9630  TPrefDirElement PE2(TE, TE.Link[2], 2, TE.Link[3], 3, VecPos);
9632  TPrefDirElement PE3(TE, TE.Link[3], 3, TE.Link[2], 2, VecPos);
9634  }
9635  else if((TE.TrackType == Simple) || (TE.TrackType == Buffers) || (TE.TrackType == SignalPost) || (TE.TrackType == Continuation) ||
9636  (TE.TrackType == GapJump) || (TE.TrackType == FootCrossing))
9637  // need to list these explicitly since inactive elements will still be 'found' if there is an active element
9638  // at the same position
9639  {
9640  TPrefDirElement PE0(TE, TE.Link[0], 0, TE.Link[1], 1, VecPos);
9642  TPrefDirElement PE1(TE, TE.Link[1], 1, TE.Link[0], 0, VecPos);
9644  }
9645  }
9646  }
9648  ResetChangedFileDataAndCaption(22, false);
9649  // RlyFile = false; - don't alter this just for PrefDir changes
9650  Level1Mode = BaseMode; // call this first to clear everything, then set PrefDir mode
9651  SetLevel1Mode(30);
9653  SetLevel1Mode(31); // calls Clearand... to display all PrefDirs
9654  Utilities->CallLogPop(1549);
9655  }
9656  catch(const Exception &e)
9657  {
9658  ErrorLog(155, e.Message);
9659  }
9660 }
9661 
9662 // ---------------------------------------------------------------------------
9663 void __fastcall TInterface::CancelSelectionMenuItemClick(TObject *Sender)
9664 {
9665  try
9666  {
9667  TrainController->LogEvent("CancelSelectionClick");
9668  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CancelSelectionClick");
9669  ClearandRebuildRailway(46); // to remove the selection outline
9670  SelectionValid = false;
9671  Track->CopyFlag = false;
9673  ResetSelectRect();
9674  if(Level1Mode == TrackMode)
9675  {
9676  SetLevel1Mode(76);
9678  SetLevel2TrackMode(39);
9679  }
9680  else if(Level1Mode == PrefDirMode)
9681  {
9682  SetLevel1Mode(32);
9683  }
9684  Utilities->CallLogPop(1413);
9685  }
9686  catch(const Exception &e)
9687  {
9688  ErrorLog(156, e.Message);
9689  }
9690 }
9691 
9692 // ---------------------------------------------------------------------------
9693 void __fastcall TInterface::LoadTimetableMenuItemClick(TObject *Sender)
9694 {
9695  try
9696  {
9697  TrainController->LogEvent("LoadTimetableMenuItemClick");
9698  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LoadTimetableMenuItemClick");
9699  TimetableDialog->Filter = "Timetable file (*.ttb)|*.ttb";
9700  // reset all message flags, stops them being given twice new at v2.4.0
9701  TrainController->SSHigh = false;
9702  TrainController->MRSHigh = false;
9703  TrainController->MRSLow = false;
9704  TrainController->MassHigh = false;
9705  TrainController->BFHigh = false;
9706  TrainController->BFLow = false;
9707  TrainController->PwrHigh = false;
9708  TrainController->SigSHigh = false;
9709  TrainController->SigSLow = false;
9710  if(TimetableDialog->Execute())
9711  {
9712  if(TimetableDialog->InitialDir != TPath::GetDirectoryName(TimetableDialog->FileName))//new at v2.6.0 to retain a new directory
9713  {
9714  TimetableDialog->InitialDir = TPath::GetDirectoryName(TimetableDialog->FileName);
9715  SaveTTDialog->InitialDir = TPath::GetDirectoryName(TimetableDialog->FileName);
9716  }
9717  TrainController->LogEvent("LoadTimetable " + TimetableDialog->FileName);
9718  bool CheckLocationsExistInRailwayTrue = true;
9719  if(TrainController->TimetableIntegrityCheck(0, AnsiString(TimetableDialog->FileName).c_str(), true, CheckLocationsExistInRailwayTrue))
9720  // true for GiveMessages
9721  {
9722  Screen->Cursor = TCursor(-11); // Hourglass;
9723  std::ifstream TTBLFile(AnsiString(TimetableDialog->FileName).c_str(), std::ios_base::binary);
9724  if(TTBLFile.is_open())
9725  {
9726  bool SessionFileFalse = false;
9727  if(BuildTrainDataVectorForLoadFile(0, TTBLFile, true, CheckLocationsExistInRailwayTrue, SessionFileFalse)) // true for GiveMessages
9728  {
9729  SaveTempTimetableFile(0, TimetableDialog->FileName);
9730  } // don't need an 'else' as messages given in BuildTrainDataVectorForLoadFile
9731  }
9732  else
9733  {
9734  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
9735  }
9736  Screen->Cursor = TCursor(-2); // Arrow
9737  } // if(TimetableIntegrityCheck
9738  else
9739  ShowMessage("Timetable preliminary integrity check failed - unable to load");
9740  } // if(TimetableDialog->Execute())
9741  // else ShowMessage("Load Aborted");
9742  Utilities->CallLogPop(752);
9743  }
9744  catch(const Exception &e)
9745  {
9746  ErrorLog(34, e.Message);
9747  }
9748 }
9749 
9750 // ---------------------------------------------------------------------------
9751 void __fastcall TInterface::TakeSignallerControlMenuItemClick(TObject *Sender)
9752 {
9753  try
9754  {
9755  TrainController->LogEvent("SignallerControl1Click");
9756  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SignallerControl1Click");
9758  Train.SignallerStoppingFlag = false;
9759  Train.TrainMode = Signaller;
9760  if(Train.MaxRunningSpeed > Train.SignallerMaxSpeed)
9761  {
9762  Train.MaxRunningSpeed = Train.SignallerMaxSpeed;
9763  }
9764  if(Train.Stopped())
9765  Train.SignallerStopped = true; // condition added at v2.4.0 to allow for taking sig control of failed moving trains
9766  Train.CallingOnFlag = false; // in case was set, wouldn't start anyway if called on as SignallerStopped = true
9768  Train.PlotTrain(5, Display);
9769  AnsiString LocName = "";
9770  if(Train.LeadElement > -1)
9771  {
9772  LocName = Track->TrackElementAt(633, Train.LeadElement).ActiveTrackElementName;
9773  }
9774  if((LocName == "") && (Train.MidElement > -1))
9775  {
9776  LocName = Track->TrackElementAt(634, Train.MidElement).ActiveTrackElementName;
9777  }
9778 
9779  // store the value that allow restoration of tt control or not - RestoreTimetableLocation
9780  if(Train.StoppedAtLocation && (LocName != ""))
9781  {
9782  Train.RestoreTimetableLocation = LocName;
9783  }
9784  else
9785  {
9786  Train.RestoreTimetableLocation = "";
9787  }
9788 
9789  // check whether need to offer 'pass red signal'
9790  if(!Train.StoppedAtSignal && Train.StoppedAtLocation)
9791  {
9792  int NextElementPosition = Track->TrackElementAt(775, Train.LeadElement).Conn[Train.LeadExitPos];
9793  int NextEntryPos = Track->TrackElementAt(776, Train.LeadElement).ConnLinkPos[Train.LeadExitPos];
9794  if((NextElementPosition > -1) && (NextEntryPos > -1))
9795  {
9796  if((Track->TrackElementAt(777, NextElementPosition).Config[Track->GetNonPointsOppositeLinkPos(NextEntryPos)] == Signal) &&
9797  (Track->TrackElementAt(778, NextElementPosition).Attribute == 0))
9798  { // set both StoppedAtLocation & StoppedAtSignal, so that 'pass red signal' is offered in popup menu rather than move
9799  // forwards, but don't change the background colour so still shows as stopped at location
9800  Train.StoppedAtSignal = true;
9801  }
9802  }
9803  }
9804  // find element ID if no locname
9805  if((LocName == "") && Train.LeadElement > -1)
9806  {
9807  LocName = Track->TrackElementAt(635, Train.LeadElement).ElementID;
9808  }
9809  if((LocName == "") && (Train.MidElement > -1))
9810  {
9811  LocName = Track->TrackElementAt(636, Train.MidElement).ElementID;
9812  }
9813  Train.LogAction(0, Train.HeadCode, "", TakeSignallerControl, LocName, TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
9814  Utilities->CallLogPop(1772);
9815  }
9816  catch(const Exception &e)
9817  {
9818  ErrorLog(157, e.Message);
9819  }
9820 }
9821 
9822 // ---------------------------------------------------------------------------
9823 
9824 void __fastcall TInterface::TimetableControlMenuItemClick(TObject *Sender)
9825 {
9826  try
9827  {
9828  TrainController->LogEvent("TimetableControlMenuItemClick");
9829  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TimetableControlMenuItemClick");
9831  Train.SignallerStoppingFlag = false;
9832  Train.TrainMode = Timetable;
9833  Train.SignallerStopped = false;
9834  Train.StoppedAfterSPAD = false;
9835  Train.SPADFlag = false;
9838 // red headcode[0]
9839  Train.PlotTrain(6, Display);
9840  AnsiString LocName = "";
9841  if(Train.LeadElement > -1)
9842  {
9843  LocName = Track->TrackElementAt(645, Train.LeadElement).ActiveTrackElementName;
9844  }
9845  if((LocName == "") && (Train.MidElement > -1))
9846  {
9847  LocName = Track->TrackElementAt(647, Train.MidElement).ActiveTrackElementName;
9848  }
9849  if((LocName == "") && Train.LeadElement > -1)
9850  {
9851  LocName = Track->TrackElementAt(646, Train.LeadElement).ElementID;
9852  }
9853  if((LocName == "") && (Train.MidElement > -1))
9854  {
9855  LocName = Track->TrackElementAt(648, Train.MidElement).ElementID;
9856  }
9857  if((Train.ActionVectorEntryPtr->LocationType == AtLocation) && (LocName == Train.ActionVectorEntryPtr->LocationName))
9858  {
9859  Train.StoppedAtLocation = true;
9860  Train.LastActionTime = TrainController->TTClockTime; // by itself this only affects trains that have still to arrive, if waiting to
9861  // depart the departure time & TRS time have already been calculated so need to
9862  // force a recalculation - see below
9863  Train.DepartureTimeSet = false; // force it to be recalculated based on new LastActionTime (if waiting to arrive this is false anyway)
9864  if(!Train.TrainFailed)
9865  {
9867  }
9868  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
9869  if((Train.ActionVectorEntryPtr->FormatType == TimeLoc) && (Train.ActionVectorEntryPtr->ArrivalTime >= TDateTime(0)))
9870  { // Timetable indicates that train still waiting to arrive for a TimeLoc arrival so send message and mark as arrived
9871  Train.LogAction(28, Train.HeadCode, "", Arrive, LocName, Train.ActionVectorEntryPtr->ArrivalTime, Train.ActionVectorEntryPtr->Warning);
9872  Train.ActionVectorEntryPtr++; // advance pointer past arrival //added at v1.2.0
9873  }
9874  else if((Train.ActionVectorEntryPtr->FormatType == TimeTimeLoc) && !(Train.TimeTimeLocArrived))
9875  { // Timetable indicates that train still waiting to arrive for a TimeTimeLoc arrival so send message and mark as arrived
9876  Train.LogAction(29, Train.HeadCode, "", Arrive, LocName, Train.ActionVectorEntryPtr->ArrivalTime, Train.ActionVectorEntryPtr->Warning);
9877  Train.TimeTimeLocArrived = true;
9878  // NB: No need for 'Train.ActionVectorEntryPtr++' because still to act on the departure time
9879  }
9880  }
9881  else
9882  {
9883  int NextElementPos = -1; // addition for v1.3.2 due to Carwyn Thomas error
9884  int NextEntryPos = -1; // ---ditto---
9885  if(Train.LeadElement > -1) // ---ditto---
9886  { // ---ditto---
9887  NextElementPos = Track->TrackElementAt(658, Train.LeadElement).Conn[Train.LeadExitPos]; // had 'int' prefix before additions
9888  NextEntryPos = Track->TrackElementAt(659, Train.LeadElement).ConnLinkPos[Train.LeadExitPos]; // ---ditto---
9889  } // ---ditto---
9890  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
9891  if(!Train.TrainFailed)
9892  {
9893  Train.PlotTrainWithNewBackgroundColour(31, clNormalBackground, Display); // to remove other background if was present, moved from
9894  } // within Train.AbleToMove at v2.4.0 to cancel signal stop background
9895  if(Train.AbleToMove(1)) // if has no power
9896  {
9897  Train.EntrySpeed = 0; // moved from below for v1.3.2 after Carwyn Thomas error
9898  Train.EntryTime = TrainController->TTClockTime; // ---Ditto---
9899  Train.FirstHalfMove = true; // ---Ditto---
9900  if((NextElementPos > -1) && (NextEntryPos > -1)) // changed from if(NextElementPos >= 0) as above
9901  {
9902  // Train.EntrySpeed = 0;
9903  // Train.EntryTime = TrainController->TTClockTime;
9904  // Train.FirstHalfMove = true;
9905  Train.SetTrainMovementValues(15, NextElementPos, NextEntryPos);
9906  }
9907  // else follow the continuations //added these 3 conditions for v1.3.2 after Carwyn Thomas error
9908  else if((Train.LeadElement > -1) && (Track->TrackElementAt(894, Train.LeadElement).TrackType == Continuation))
9909  {
9910  Train.SetTrainMovementValues(21, Train.LeadElement, Train.LeadEntryPos); // Use LeadElement for calcs if lead is a continuation
9911  }
9912  else if((Train.MidElement > -1) && (Track->TrackElementAt(895, Train.MidElement).TrackType == Continuation))
9913  {
9914  Train.SetTrainMovementValues(22, Train.MidElement, Train.MidEntryPos); // Use MidElement for calcs if Mid is a continuation
9915  }
9916  else if((Train.LagElement > -1) && (Track->TrackElementAt(896, Train.LagElement).TrackType == Continuation))
9917  {
9918  Train.SetTrainMovementValues(23, Train.LagElement, Train.LagEntryPos); // Use LagElement for calcs if Lag is a continuation
9919  }
9920  }
9921  else if(Train.StoppedAtSignal)
9922  {
9923  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
9924  if(!Train.TrainFailed)
9925  {
9927  }
9928  // TrainController->LogActionError(42, Train.HeadCode, "", SignalHold, Track->TrackElementAt(757, NextElementPos).ElementID);
9929  }
9930  }
9931  Train.LogAction(1, Train.HeadCode, "", RestoreTimetableControl, LocName, TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
9932  Utilities->CallLogPop(1195);
9933  }
9934  catch(const Exception &e)
9935  {
9936  ErrorLog(158, e.Message);
9937  }
9938 }
9939 
9940 // ---------------------------------------------------------------------------
9941 
9942 void __fastcall TInterface::ChangeDirectionMenuItemClick(TObject *Sender)
9943 {
9944  try
9945  {
9946  TrainController->LogEvent("ChangeDirectionMenuItemClick");
9947  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ChangeDirectionMenuItemClick");
9949  Train.SignallerStoppingFlag = false;
9950  Train.SignallerChangeTrainDirection(0); // this unplots & replots train, which checks for facing signal and sets StoppedAtSignal if req'd
9951  Train.SignallerStopped = true;
9952  AnsiString LocName = "";
9953  if(Train.LeadElement > -1)
9954  {
9955  LocName = Track->TrackElementAt(637, Train.LeadElement).ActiveTrackElementName;
9956  }
9957  if((LocName == "") && (Train.MidElement > -1))
9958  {
9959  LocName = Track->TrackElementAt(638, Train.MidElement).ActiveTrackElementName;
9960  }
9961  if((LocName == "") && Train.LeadElement > -1)
9962  {
9963  LocName = Track->TrackElementAt(639, Train.LeadElement).ElementID;
9964  }
9965  if((LocName == "") && (Train.MidElement > -1))
9966  {
9967  LocName = Track->TrackElementAt(640, Train.MidElement).ElementID;
9968  }
9969  Train.LogAction(2, Train.HeadCode, "", SignallerChangeDirection, LocName, TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
9970  Utilities->CallLogPop(1196);
9971  }
9972  catch(const Exception &e)
9973  {
9974  ErrorLog(159, e.Message);
9975  }
9976 }
9977 // ---------------------------------------------------------------------------
9978 
9979 void __fastcall TInterface::MoveForwardsMenuItemClick(TObject *Sender)
9980 {
9981  try
9982  {
9983  TrainController->LogEvent("MoveForwardsMenuItemClick");
9984  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MoveForwardsMenuItemClick");
9986  Train.SignallerStoppingFlag = false;
9987  if(!Train.AbleToMove(2))
9988  { // shouldn't be here as when unable to move MoveForwards shouldn't be enabled, but leave in as a precaution
9989  Utilities->CallLogPop(1197);
9990  return;
9991  }
9992  Train.SignallerStopped = false;
9993  Train.StoppedAfterSPAD = false; // in case had been set
9994  Train.SPADFlag = false;
9995  Train.StoppedAtLocation = false; // may not have been set but reset anyway
9996  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
9998  Train.EntrySpeed = 0;
10000  Train.FirstHalfMove = true;
10001  int NextElementPos = -1; // addition for v1.3.2 due to Carwyn Thomas error
10002  int NextEntryPos = -1; // ---ditto---
10003  if(Train.LeadElement > -1) // ---ditto---
10004  { // ---ditto---
10005  NextElementPos = Track->TrackElementAt(652, Train.LeadElement).Conn[Train.LeadExitPos]; // had 'int' prefix before additions
10006  NextEntryPos = Track->TrackElementAt(657, Train.LeadElement).ConnLinkPos[Train.LeadExitPos]; // ---ditto---
10007  } // ---ditto---
10008  if((NextElementPos > -1) && (NextEntryPos > -1))
10009  {
10010  Train.SetTrainMovementValues(14, NextElementPos, NextEntryPos); // NextElement is the element to be entered
10011  }
10012  // else follow the continuations
10013  else if((Train.LeadElement > -1) && (Track->TrackElementAt(784, Train.LeadElement).TrackType == Continuation))
10014  {
10015  Train.SetTrainMovementValues(17, Train.LeadElement, Train.LeadEntryPos); // Use LeadElement for calcs if lead is a continuation
10016  }
10017  else if((Train.MidElement > -1) && (Track->TrackElementAt(785, Train.MidElement).TrackType == Continuation))
10018  {
10019  Train.SetTrainMovementValues(18, Train.MidElement, Train.MidEntryPos); // Use MidElement for calcs if Mid is a continuation
10020  }
10021  else if((Train.LagElement > -1) && (Track->TrackElementAt(786, Train.LagElement).TrackType == Continuation))
10022  {
10023  Train.SetTrainMovementValues(19, Train.LagElement, Train.LagEntryPos); // Use LagElement for calcs if Lag is a continuation
10024  }
10025  Train.LogAction(3, Train.HeadCode, "", SignallerMoveForwards, "", TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
10026  Utilities->CallLogPop(1198);
10027  }
10028  catch(const Exception &e)
10029  {
10030  ErrorLog(160, e.Message);
10031  }
10032 }
10033 // ---------------------------------------------------------------------------
10034 
10035 void __fastcall TInterface::SignallerJoinedByMenuItemClick(TObject *Sender)
10036 { // new at v2.4.0
10037  try
10038  {
10039  TrainController->LogEvent("JoinedByMenuItemClick");
10040  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",JoinedByMenuItemClick");
10041  TTrain *TrainToBeJoinedBy;
10043  if(ThisTrain.IsThereAnAdjacentTrain(1, TrainToBeJoinedBy)) // this must come before both powers zero check in order to set a valid TrainToBeJoinedBy
10044  {
10045  if(TrainToBeJoinedBy->TrainMode != Signaller)
10046  {
10047  TrainController->StopTTClockMessage(91, "Adjacent train must be under signaller control in order to join");
10048  Utilities->CallLogPop(2156);
10049  return;
10050  }
10051  // here if there is an adjacent train under signaller control
10052  if((TrainToBeJoinedBy->PowerAtRail < 1) && (ThisTrain.PowerAtRail < 1))
10053  {
10054  ShowMessage("Can't join two trains when both are without power");
10055  Utilities->CallLogPop(2157);
10056  return;
10057  }
10058  AnsiString TrainToBeJoinedByHeadCode = TrainToBeJoinedBy->HeadCode;
10059  // set new values for mass etc
10060  double OtherBrakeForce = TrainToBeJoinedBy->MaxBrakeRate * TrainToBeJoinedBy->Mass;
10061  double OwnBrakeForce = ThisTrain.MaxBrakeRate * ThisTrain.Mass;
10062  double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->Mass + ThisTrain.Mass);
10063  ThisTrain.Mass += TrainToBeJoinedBy->Mass;
10064  ThisTrain.MaxBrakeRate = CombinedBrakeRate;
10065  ThisTrain.PowerAtRail += TrainToBeJoinedBy->PowerAtRail;
10066  ThisTrain.AValue = sqrt(2 * ThisTrain.PowerAtRail / ThisTrain.Mass);
10067 
10068  TrainToBeJoinedBy->TrainGone = true; // this will cause other train to be deleted
10069  TrainToBeJoinedBy->JoinedOtherTrainFlag = true;
10070  AnsiString LocName = "";
10071  if(ThisTrain.LeadElement > -1)
10072  {
10073  LocName = Track->TrackElementAt(979, ThisTrain.LeadElement).ActiveTrackElementName;
10074  }
10075  if((LocName == "") && (ThisTrain.MidElement > -1))
10076  {
10077  LocName = Track->TrackElementAt(980, ThisTrain.MidElement).ActiveTrackElementName;
10078  }
10079  if((LocName == "") && ThisTrain.LeadElement > -1)
10080  {
10081  LocName = Track->TrackElementAt(981, ThisTrain.LeadElement).ElementID;
10082  }
10083  if((LocName == "") && (ThisTrain.MidElement > -1))
10084  {
10085  LocName = Track->TrackElementAt(982, ThisTrain.MidElement).ElementID;
10086  }
10087  ThisTrain.StoppedWithoutPower = true;
10088  if(ThisTrain.PowerAtRail >= 1)
10089  {
10090  ThisTrain.StoppedWithoutPower = false;
10091  }
10092  ThisTrain.TrainFailed = false; // if had failed then no longer failed, even if joining train has no power
10093  if(!ThisTrain.StoppedAtLocation)
10094  {
10095  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10097  }
10098  else
10099  {
10100  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10102  }
10103  ThisTrain.SignallerStopped = true; // maybe as well as stopped without power, thought that takes precedence in floating window
10104  ThisTrain.LogAction(34, ThisTrain.HeadCode, TrainToBeJoinedBy->HeadCode, SignallerJoin, LocName, TDateTime(0), false); // TDateTime isn't used
10105  ThisTrain.ZeroPowerNoFrontSplitMessage = false; // added at v2.4.0, no need to include TrainToBeJoinedBy as that will be removed
10106  ThisTrain.ZeroPowerNoRearSplitMessage = false;
10107  ThisTrain.FailedTrainNoFinishJoinMessage = false;
10108  ThisTrain.ZeroPowerNoJoinedByMessage = false;
10109  ThisTrain.ZeroPowerNoCDTMessage = false;
10110  ThisTrain.ZeroPowerNoNewServiceMessage = false;
10112  ThisTrain.ZeroPowerNoRepeatShuttleMessage = false;
10114  Utilities->CallLogPop(2158);
10115  }
10116  }
10117  catch(const Exception &e)
10118  {
10119  ErrorLog(207, e.Message);
10120  }
10121 }
10122 // ---------------------------------------------------------------------------
10123 
10124 void __fastcall TInterface::RepairFailedTrainMenuItemClick(TObject *Sender)
10125 { // added at v2.4.0
10126  try
10127  {
10128  TrainController->LogEvent("RepairFailedTrainMenuItemClick");
10129  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RepairFailedTrainMenuItemClick");
10131  Train.TrainFailed = false;
10132  Train.StoppedWithoutPower = false;
10133  Train.SignallerStopped = true;
10134  if(!Train.StoppedAtLocation)
10135  {
10136  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10138  }
10139  else
10140  {
10141  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10143  }
10144  Train.PowerAtRail = Train.OriginalPowerAtRail; // recover from original value, new at v2.4.0
10145  Train.AValue = sqrt(2 * Train.PowerAtRail / Train.Mass);
10146  Train.SetTrainMovementValues(24, Train.LeadElement, Train.LeadEntryPos);
10147  AnsiString LocName = "";
10148  if(Train.LeadElement > -1)
10149  {
10150  LocName = Track->TrackElementAt(983, Train.LeadElement).ActiveTrackElementName;
10151  }
10152  if((LocName == "") && (Train.MidElement > -1))
10153  {
10154  LocName = Track->TrackElementAt(984, Train.MidElement).ActiveTrackElementName;
10155  }
10156  if((LocName == "") && Train.LeadElement > -1)
10157  {
10158  LocName = Track->TrackElementAt(985, Train.LeadElement).ElementID;
10159  }
10160  if((LocName == "") && (Train.MidElement > -1))
10161  {
10162  LocName = Track->TrackElementAt(986, Train.MidElement).ElementID;
10163  }
10164  Train.LogAction(35, Train.HeadCode, "", RepairFailedTrain, LocName, TrainController->TTClockTime, false); // false for no warning
10165  Train.ZeroPowerNoFrontSplitMessage = false;
10166  Train.ZeroPowerNoRearSplitMessage = false;
10167  Train.FailedTrainNoFinishJoinMessage = false;
10168  Train.ZeroPowerNoJoinedByMessage = false;
10169  Train.ZeroPowerNoCDTMessage = false;
10170  Train.ZeroPowerNoNewServiceMessage = false;
10172  Train.ZeroPowerNoRepeatShuttleMessage = false;
10174  Utilities->CallLogPop(2159);
10175  }
10176  catch(const Exception &e)
10177  {
10178  ErrorLog(208, e.Message);
10179  }
10180 }
10181 
10182 // ---------------------------------------------------------------------------
10183 
10184 void __fastcall TInterface::SignallerControlStopMenuItemClick(TObject *Sender)
10185 {
10186  try
10187  {
10188  TrainController->LogEvent("SignallerControlStopMenuItemClick");
10189  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SignallerControlStopMenuItemClick");
10192  if(Train.LeadElement > -1)
10193  {
10194  if(Track->TrackElementAt(787, Train.LeadElement).Conn[Train.LeadExitPos] > -1)
10195  {
10196  Train.SignallerStoppingFlag = true;
10197  Train.SignallerStopBrakeRate = 0;
10198  Train.LogAction(24, Train.HeadCode, "", SignallerControlStop, "", TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
10199  }
10200  else
10202  }
10203  else
10205  Utilities->CallLogPop(1553);
10206  }
10207  catch(const Exception &e)
10208  {
10209  ErrorLog(161, e.Message);
10210  }
10211 }
10212 
10213 // ---------------------------------------------------------------------------
10214 void __fastcall TInterface::PassRedSignalMenuItemClick(TObject *Sender)
10215 {
10216  try
10217  {
10218  TrainController->LogEvent("PassRedSignalMenuItemClick");
10219  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PassRedSignalMenuItemClick");
10221  Train.SignallerStoppingFlag = false;
10222  int NextElementPos = Track->TrackElementAt(712, Train.LeadElement).Conn[Train.LeadExitPos];
10223  if(NextElementPos < 0)
10224  {
10225  throw Exception("Error, no element in front in PassRedSignalMenuItemClick");
10226  }
10227  TTrackElement &TrackElement = Track->TrackElementAt(653, NextElementPos);
10228 /* drop this error as may be some circumstances where behind a signal in sig mode but not stopped at signal
10229  if(!Train.StoppedAtSignal)
10230  {
10231  throw Exception("Error, not StoppedAtSignal in PassRedSignalMenuItemClick");
10232  }
10233 */
10234  if(TrackElement.TrackType != SignalPost)
10235  {
10236  throw Exception("Error, next element not a signal type in PassRedSignalMenuItemClick");
10237  }
10238  Train.SignallerStopped = false;
10239  Train.StoppedAtLocation = false; // may have started at station in signaller mode and also at a red signal, in this case both SignallerStopped
10240  // and StoppedAtLocation are set but the background colour stays pale green for station, not signal,
10241  // since no need to alert the user
10242  Train.StoppedAfterSPAD = false; // in case had been set
10243  Train.SPADFlag = false;
10244  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10246  Train.AllowedToPassRedSignal = true;
10247  Train.LogAction(4, Train.HeadCode, "", SignallerPassRedSignal, "", TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
10248  Utilities->CallLogPop(1199);
10249  }
10250  catch(const Exception &e)
10251  {
10252  ErrorLog(162, e.Message);
10253  }
10254 }
10255 // ---------------------------------------------------------------------------
10256 
10257 void __fastcall TInterface::StepForwardMenuItemClick(TObject *Sender)
10258 {
10259  try
10260  {
10261  TrainController->LogEvent("StepForwardMenuItemClick");
10262  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",StepForwardMenuItemClick");
10264  Train.SignallerStoppingFlag = false;
10265  Train.SignallerStopped = false;
10266  Train.StoppedAtLocation = false; // may have started at station in signaller mode and also at a red signal, in this case both SignallerStopped
10267  // and StoppedAtLocation are set but the background colour stays pale green for station, not signal,
10268  // since no need to alert the user
10269  Train.StoppedAfterSPAD = false; // in case had been set
10270  Train.SPADFlag = false;
10271  Train.StepForwardFlag = true;
10272  Train.AllowedToPassRedSignal = true; // in case at a signal, will clear when half-way into next element whether a signal or not
10273  // ok to call PlotTrainWithNewBackgroundColour here as PlotElements already set to Lead, Mid & Lag elements
10275  Train.LogAction(32, Train.HeadCode, "", SignallerStepForward, "", TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
10276  int NextElementPos = -1;
10277 // addition for v1.3.2 due to Carwyn Thomas error: can't select StepForwardMenuItem if exiting at a continuation but leave this in anyway
10278  int NextEntryPos = -1; // ---ditto---
10279  if(Train.LeadElement > -1) // ---ditto---
10280  { // ---ditto---
10281  NextElementPos = Track->TrackElementAt(804, Train.LeadElement).Conn[Train.LeadExitPos]; // had 'int' prefix before additions
10282  NextEntryPos = Track->TrackElementAt(805, Train.LeadElement).ConnLinkPos[Train.LeadExitPos]; // ---ditto---
10283  } // ---ditto---
10284  if((NextElementPos > -1) && (NextEntryPos > -1))
10285  { // call this after StepForwardFlag set
10286  Train.EntrySpeed = 0;
10288  Train.FirstHalfMove = true;
10289  Train.SetTrainMovementValues(20, NextElementPos, NextEntryPos); // NextElement is the element to be entered
10290  }
10291  Utilities->CallLogPop(1800);
10292  }
10293  catch(const Exception &e)
10294  {
10295  ErrorLog(163, e.Message);
10296  }
10297 }
10298 
10299 // ---------------------------------------------------------------------------
10300 
10301 void __fastcall TInterface::RemoveTrainMenuItemClick(TObject *Sender)
10302 {
10303  try
10304  {
10305  TrainController->LogEvent("RemoveTrainMenuItemClick");
10306  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",RemoveTrainMenuItemClick");
10308  if((!Train.Derailed) && (!Train.Crashed))
10309  {
10310  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
10312  UnicodeString Message = UnicodeString(Train.HeadCode) + " will be removed from the railway - proceed?";
10313  int button = Application->MessageBox(Message.c_str(), L"Please confirm", MB_YESNO);
10314  TrainController->BaseTime = TDateTime::CurrentDateTime();
10316  if(button == IDNO)
10317  {
10318  Utilities->CallLogPop(1801);
10319  return;
10320  }
10321  }
10322  Train.SignallerStoppingFlag = false;
10323  Train.TrainGone = true; // will be removed by TTrainController::Operate
10324  Train.SignallerRemoved = true;
10325  Train.TrainDataEntryPtr->TrainOperatingDataVector.at(Train.RepeatNumber).RunningEntry = Exited;
10326  AnsiString LocName = "";
10327  if(Train.LeadElement > -1)
10328  {
10329  LocName = Track->TrackElementAt(641, Train.LeadElement).ActiveTrackElementName;
10330  }
10331  if((LocName == "") && (Train.MidElement > -1))
10332  {
10333  LocName = Track->TrackElementAt(642, Train.MidElement).ActiveTrackElementName;
10334  }
10335  if((LocName == "") && Train.LeadElement > -1)
10336  {
10337  LocName = Track->TrackElementAt(643, Train.LeadElement).ElementID;
10338  }
10339  if((LocName == "") && (Train.MidElement > -1))
10340  {
10341  LocName = Track->TrackElementAt(644, Train.MidElement).ElementID;
10342  }
10343  TTrackElement *TrackElementPtr;
10344  int RouteNumber;
10345  TAllRoutes::TRouteType RouteType;
10346  if(Train.LeadElement > -1)
10347  {
10348  TrackElementPtr = &(Track->TrackElementAt(673, Train.LeadElement));
10349  // remove TrainIDs from track element, added at v2.4.0
10350  if(TrackElementPtr->TrackType == Bridge)
10351  {
10352  if(Train.LeadExitPos > 1)
10353  {
10354  TrackElementPtr->TrainIDOnBridgeTrackPos23 = -1;
10355  }
10356  else
10357  {
10358  TrackElementPtr->TrainIDOnBridgeTrackPos01 = -1;
10359  }
10360  }
10361  else
10362  {
10363  TrackElementPtr->TrainIDOnElement = -1;
10364  }
10365  // reset any CallingOnSet flags for signals, if facing wrong way doesn't matter, shouldn't be set anyay
10366  if((TrackElementPtr->TrackType == SignalPost) && TrackElementPtr->CallingOnSet)
10367  {
10368  TrackElementPtr->CallingOnSet = false;
10369  Track->PlotSignal(6, *TrackElementPtr, Display);
10370  }
10371 // [added at v1.3.0] here check if on an automatic signals route and if so reset signals for the entire route from the
10372 // start of the route - after the train has been removed, use LeadElement and also MidElement (if no autosigs route at LeadElement) just to be sure
10373  RouteType = AllRoutes->GetRouteTypeAndNumber(27, Train.LeadElement, Train.LeadEntryPos, RouteNumber);
10374  if(RouteType == TAllRoutes::AutoSigsRoute)
10375  {
10378  }
10379 // end of addition
10380 
10381 //erase a stub route if there is one, added at v2.6.1
10382 //first element of route is immediately in front of the train
10383  if(Train.LeadExitPos >= 0)
10384  {
10385  TTrackElement LeadTrackElement = Track->TrackElementAt(1013, Train.LeadElement);
10386  int FirstRouteElementVecPos = LeadTrackElement.Conn[Train.LeadExitPos];
10387  int FirstRouteLinkPos = LeadTrackElement.ConnLinkPos[Train.LeadExitPos];
10388  RouteType = AllRoutes->GetRouteTypeAndNumber(39, FirstRouteElementVecPos, FirstRouteLinkPos, RouteNumber);
10389  if(RouteType == TAllRoutes::NotAutoSigsRoute) //red or green route, if no route then ignore
10390  {
10391  TOneRoute &OR = AllRoutes->GetModifiableRouteAt(30, RouteNumber);
10392  TTrackElement TE = Track->TrackElementAt(1014, FirstRouteElementVecPos);
10393  if((TE.TrackType != SignalPost) && (TE.TrackType != Continuation))//all autosigs routes have signalpost or continuation at 0 so they are automatically excluded
10394  {
10395  while(OR.PrefDirSize() > 0) //remove the route up to but not including the next facing signal, in case a route extends to another signal
10396  {
10397  TPrefDirElement PDE = OR.GetFixedPrefDirElementAt(249, 0); //these will change at each element removal because OR is a reference to the real route
10398  int TVPos2 = PDE.GetTrackVectorPosition();
10399  TTrackElement TE2 = Track->TrackElementAt(1015, TVPos2);
10400  if(Track->TrackElementAt(1016, PDE.GetTrackVectorPosition()).Config[PDE.GetXLinkPos()] != Signal)
10401  {
10402  AllRoutes->RemoveRouteElement(24, TE2.HLoc, TE2.VLoc, PDE.GetELink());
10403  }
10404  else
10405  {
10406  break;
10407  }
10408  }
10409  AllRoutes->RebuildRailwayFlag = true;
10410  // to force ClearandRebuildRailway at next clock tick if not in zoom-out mode, to replot without stub route
10411  }
10412  }
10413  }
10414 //end of stub route removal addition
10415  }
10416  if(Train.MidElement > -1)
10417  {
10418  TrackElementPtr = &(Track->TrackElementAt(674, Train.MidElement));
10419  // remove TrainIDs from track element, added at v2.4.0
10420  if(TrackElementPtr->TrackType == Bridge)
10421  {
10422  if(Train.MidExitPos > 1)
10423  {
10424  TrackElementPtr->TrainIDOnBridgeTrackPos23 = -1;
10425  }
10426  else
10427  {
10428  TrackElementPtr->TrainIDOnBridgeTrackPos01 = -1;
10429  }
10430  }
10431  else
10432  {
10433  TrackElementPtr->TrainIDOnElement = -1;
10434  }
10435  if((TrackElementPtr->TrackType == SignalPost) && TrackElementPtr->CallingOnSet)
10436  {
10437  TrackElementPtr->CallingOnSet = false;
10438  Track->PlotSignal(7, *TrackElementPtr, Display);
10439  }
10440 // [added at v1.3.0 as above]
10442  {
10443  RouteType = AllRoutes->GetRouteTypeAndNumber(28, Train.MidElement, Train.MidEntryPos, RouteNumber);
10444  if(RouteType == TAllRoutes::AutoSigsRoute)
10445  {
10448  }
10449  }
10450 // end of addition
10451  }
10452  if(Train.LeadElement > -1)
10453  // addition for v1.3.2 after Carwyn Thomas fault reported 24/05/15 - need to check if exiting at continuation (LeadElement == -1) as if so fails at next line
10454  {
10455  if(Track->TrackElementAt(675, Train.LeadElement).Conn[Train.LeadExitPos] > -1)
10456  {
10457  TrackElementPtr = &(Track->TrackElementAt(676, Track->TrackElementAt(677, Train.LeadElement).Conn[Train.LeadExitPos]));
10458  if((TrackElementPtr->TrackType == SignalPost) && TrackElementPtr->CallingOnSet)
10459  {
10460  TrackElementPtr->CallingOnSet = false;
10461  Track->PlotSignal(8, *TrackElementPtr, Display);
10462  }
10463  }
10464  }
10465  Train.LogAction(5, Train.HeadCode, "", RemoveTrain, LocName, TDateTime(0), false); // TDateTime is a dummy entry, false for no warning
10466  if(Train.ActionVectorEntryPtr->Command != "Frh") // if remaining at location no point in sending 'failed to terminate' message
10467  {
10468  Train.SendMissedActionLogs(0, -1, Train.ActionVectorEntryPtr); // -1 is a marker for send messages for all remaining
10469  } // entries, including Fer if present
10470  Utilities->CallLogPop(1200);
10471  }
10472  catch(const Exception &e)
10473  {
10474  ErrorLog(164, e.Message);
10475  }
10476 }
10477 
10478 // ---------------------------------------------------------------------------
10479 
10480 void __fastcall TInterface::ErrorButtonClick(TObject *Sender)
10481  // to terminate after error message given
10482 {
10483  ErrorMessage->Visible = false;
10484  ErrorMessageStoreImage->Visible = false;
10485  ErrorButton->Visible = false;
10486  Display->GetImage()->Visible = true;
10487  Application->Terminate();
10488 }
10489 
10490 // ---------------------------------------------------------------------------
10491 void __fastcall TInterface::PerformancePanelLabelStartDrag(TObject *Sender, TDragObject *&DragObject)
10492 {
10493  try
10494  {
10495  TrainController->LogEvent("PerformancePanelLabelStartDrag");
10496  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PerformancePanelLabelStartDrag");
10497  PerformancePanelDragStartX = Mouse->CursorPos.x - PerformancePanel->Left;
10498  PerformancePanelDragStartY = Mouse->CursorPos.y - PerformancePanel->Top;
10499  Utilities->CallLogPop(1202);
10500  }
10501  catch(const Exception &e)
10502  {
10503  ErrorLog(165, e.Message);
10504  }
10505 }
10506 // ---------------------------------------------------------------------------
10507 
10508 void __fastcall TInterface::FormClose(TObject *Sender, TCloseAction &Action)
10509 {
10510  try
10511  {
10512  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",FormClose");
10514  {
10515  UnicodeString MessageStr =
10516  "Note that leaving the track unlinked will cause preferred directions to be lost on reloading. Prevent by linking the track then resaving. Do you still wish to exit?";
10517  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
10518  if(button == IDNO)
10519  {
10520  Action = caNone; // prevents form & application from closing
10521  Utilities->CallLogPop(1712);
10522  return;
10523  }
10524  }
10526  {
10527  UnicodeString MessStr = "";
10529  {
10530  MessStr = UnicodeString("The railway and the timetable have both changed, exit without saving either?");
10531  }
10532  else if(FileChangedFlag)
10533  {
10534  MessStr = UnicodeString("The railway has changed, exit without saving?");
10535  }
10536  else
10537  {
10538  MessStr = UnicodeString("The timetable has changed, exit without saving?");
10539  }
10540  int button = Application->MessageBox(MessStr.c_str(), L"Please confirm", MB_YESNO);
10541  if(button == IDNO)
10542  {
10543  Action = caNone; // prevents form & application from closing
10544  Utilities->CallLogPop(1133);
10545  return;
10546  }
10547  }
10548 
10549  if(Level1Mode == OperMode)
10550  {
10552  {
10553  UnicodeString MessageStr = "Please note that the session will be lost if it hasn't been saved. Do you still wish to exit?";
10554  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
10556  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
10557  TrainController->BaseTime = TDateTime::CurrentDateTime();
10559  if(button == IDNO)
10560  {
10561  Action = caNone; // prevents form & application from closing
10562  Utilities->CallLogPop(969);
10563  return;
10564  }
10565  }
10567  Utilities->PerformanceFile.close();
10568  }
10569  if((TempTTFileName != "") && FileExists(TempTTFileName))
10570  {
10571  DeleteFile(TempTTFileName);
10572  }
10573  Utilities->CallLogPop(971);
10574  }
10575  catch(const Exception &e)
10576  {
10577  ErrorLog(166, e.Message);
10578  }
10579 }
10580 
10581 // ---------------------------------------------------------------------------
10582 
10583 void __fastcall TInterface::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
10584 {
10585 // TrainController->LogEvent("FormKeyDown," + AnsiString(Key));
10586 // drop event log as have too many spurious entries
10587  try
10588  {
10589  if((Shift.Contains(ssAlt)) && (Shift.Contains(ssCtrl)))
10590  {
10591  if(Key == '2')
10592  {
10593  if(CallLogTickerLabel->Visible)
10594  {
10595  CallLogTickerLabel->Visible = false;
10596  }
10597  else
10598  {
10599  CallLogTickerLabel->Visible = true;
10600  }
10601  }
10602  else if(Key == '3')
10603  {
10604  if(DevelopmentPanel->Visible)
10605  {
10606  DevelopmentPanel->Visible = false;
10607  }
10608  else
10609  {
10610  DevelopmentPanel->Visible = true;
10611  DevelopmentPanel->BringToFront();
10612  }
10613  }
10614  else if(Key == '4')
10615  {
10616  TestFunction();
10617  }
10618  else if(Key == '5')
10619  {
10620  TMsgDlgButtons Buttons;
10621  Buttons << mbYes << mbNo;
10622  if(MessageDlg("Do you wish to allow facing signals next to bridges? If so please be aware that routes cannot be truncated to these signals.", mtWarning, Buttons, 0) == mrYes)
10623  {
10625  }
10626  else
10627  {
10629  }
10630  }
10631  }
10632  else if(Shift.Contains(ssCtrl) && !Shift.Contains(ssShift) && !Shift.Contains(ssAlt))
10633  {
10634  CtrlKey = true;
10635  }
10636  else if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl) && !Shift.Contains(ssAlt))
10637  {
10638  ShiftKey = true;
10639  }
10640 
10641 // below added at v1.3.0 to allow keyboard scrolling as well as mouse button scrolling - see user suggestion on Features & Requests forum 30/09/12
10642 // the NonCTRLOrSHIFTKeyUpFlag prevents repeated viewpoint movements without keys being re-pressed
10643 // note that use the OnKeyDown event rather than OnKeyPress as suggested by the user so that the CTRL & SHIFT keys can be taken into account
10644 
10645 //at v2.4.2 the flag changed to LastNonCtrlOrShiftKeyDown to make condition specific to last key, because when a message given the key up event
10646 //is not seen as the form does not have focus, so with the flag no shortcut key will work on the first press, with this only the same shortcut key
10647 //won't work on first press and that is less likely to be used a second time on either side of the message
10648 
10649  if((Key != VK_SHIFT) && (Key != VK_CONTROL))
10650  {
10651  if(LastNonCtrlOrShiftKeyDown == Key) //same key still down rejected
10652  {
10653  return;
10654  }
10655  else
10656  {
10658  }
10659  }
10660 
10661  if(Key == VK_UP)
10662  {
10663  if(ScreenUpButton->Enabled)
10664  ScreenUpButton->Click();
10665  }
10666  else if(Key == VK_DOWN)
10667  {
10668  if(ScreenDownButton->Enabled)
10669  ScreenDownButton->Click();
10670  }
10671  else if(Key == VK_LEFT)
10672  {
10673  if(ScreenLeftButton->Enabled)
10674  ScreenLeftButton->Click();
10675  }
10676  else if(Key == VK_RIGHT)
10677  {
10678  if(ScreenRightButton->Enabled)
10679  ScreenRightButton->Click();
10680  }
10681  else if(Key == VK_HOME)
10682  {
10683  if(HomeButton->Enabled)
10684  HomeButton->Click();
10685  }
10686 // end of 1.3.0 addition
10687  else if(Key == VK_END) // added at v2.2.0 to toggle zoom using 'End' key
10688  {
10689  if(ZoomButton->Enabled)
10690  ZoomButton->Click();
10691  }
10692  else if(Key == VK_END) // added at v2.2.0 to toggle zoom using 'End' key
10693  {
10694  if(ZoomButton->Enabled)
10695  ZoomButton->Click();
10696  }
10697 
10698 //below added for v2.4.2 to add more keyboard shortcuts
10699  if(DistanceBox->Focused() || SpeedLimitBox->Focused() || MileEdit->Focused() || ChainEdit->Focused() || YardEdit->Focused() || SpeedEditBox2->Focused()
10700  || MTBFEditBox->Focused() || LocationNameTextBox->Focused() || TextBox->Focused() || PowerEditBox->Focused() || SpeedEditBox->Focused()
10701  || AddSubMinsBox->Focused() || OneEntryTimetableMemo->Focused())
10702  {// prevent letter keys interfering when these boxes have focus - many are mutually exclusive but include them all
10703  return;
10704  }
10705 
10706  if(Shift.Contains(ssShift) && !Shift.Contains(ssAlt) && !Shift.Contains(ssCtrl) && NewHomeButton->Enabled && NewHomeButton->Visible)
10707  {
10708  if(Level1Mode != TimetableMode && (Key == 'H' || Key == 'h'))//TimetablePanel uses Shift H too so disable this when it's in use
10709  {
10710  NewHomeButton->Click();
10711  }
10712  }
10713 
10714 //Operating panel
10715  if(Level1Mode == OperMode && OperatingPanel->Enabled && OperatingPanel->Visible && !Shift.Contains(ssShift) && !Shift.Contains(ssAlt))
10716  { //use Shift.Contains(ssShift etc instead of ShiftKey as that not set if pressed second after Ctrl key pressed
10717  if(!Shift.Contains(ssCtrl))
10718  {
10719  if(OperateButton->Visible && OperateButton->Enabled)
10720  {
10721  if(Level2OperMode == Operating && (Key == 'P' || Key == 'p'))
10722  {
10723  OperateButton->Click();
10724  }
10725  else if((Level2OperMode == Paused || Level2OperMode == PreStart) && (Key == 'R' || Key == 'r'))
10726  {
10727  OperateButton->Click();
10728  }
10729  }
10730  if(PresetAutoSigRoutesButton->Visible && PresetAutoSigRoutesButton->Enabled && (Key == 'A' || Key == 'a'))
10731  {
10732  PresetAutoSigRoutesButton->Click();
10733  }
10734  if(PerformanceLogButton->Visible && PerformanceLogButton->Enabled && (Key == 'L' || Key == 'l'))
10735  {
10736  PerformanceLogButton->Click();
10737  }
10738  if(CallingOnButton->Visible && CallingOnButton->Enabled && (Key == 'O' || Key == 'o'))
10739  {
10740  CallingOnButton->Click();
10741  }
10742  if(OperatorActionButton->Visible && OperatorActionButton->Enabled && (Key == 'D' || Key == 'd'))
10743  {
10744  OperatorActionButton->Click();
10745  }
10746  if(RouteCancelButton->Visible && RouteCancelButton->Enabled && (Key == 'C' || Key == 'c'))
10747  {
10748  RouteCancelButton->Click();
10749  }
10750  if(TTClockAdjButton->Visible && TTClockAdjButton->Enabled && (Key == 'T' || Key == 't'))
10751  {
10752  TTClockAdjButton->Click();
10753  }
10754  if(AutoSigsButton->Visible && AutoSigsButton->Enabled && Key == '1') //route buttons - autosigs
10755  {
10756  AutoSigsButton->Click();
10757  }
10758  if(SigPrefButton->Visible && SigPrefButton->Enabled && Key == '2') //route buttons - prefdir
10759  {
10760  SigPrefButton->Click();
10761  }
10762  if(UnrestrictedButton->Visible && UnrestrictedButton->Enabled && Key == '3') //route buttons - unrestricted
10763  {
10764  UnrestrictedButton->Click();
10765  }
10766  if(ExitOperationButton->Visible && ExitOperationButton->Enabled && Key == '\x1b')
10767  {
10768  ExitOperationButton->Click();
10769  }
10770  }
10771  else //CtrlKey down
10772  {
10773  if(SaveSessionButton->Visible && SaveSessionButton->Enabled)
10774  {
10775  SaveMenuItem->ShortCut = 0; //It's normally 16467 (Ctrl S) & will be restored in FormKeyUp. Has to be reset or will grab the key combination
10776  if(Key == 'S' || Key == 's')//so this will never execute
10777  {
10778  SaveSessionButton->Click();
10779  }
10780  }
10781  }
10782  }
10783 
10784 //Timetable clock adjust panel
10785  if(Level1Mode == OperMode && TTClockAdjPanel->Enabled && TTClockAdjPanel->Visible && !Shift.Contains(ssCtrl) && !Shift.Contains(ssAlt))
10786  { //use Shift.Contains(ssShift etc instead of ShiftKey as that not set if pressed second after Ctrl key pressed
10787  if(Shift.Contains(ssShift))
10788  {
10789  if(TTClockExitButton->Visible && TTClockExitButton->Enabled && (Key == 'A' || Key == 'a'))
10790  {
10791  TTClockExitButton->Click();
10792  }
10793  if(TTClockResetButton->Visible && TTClockResetButton->Enabled && (Key == 'R' || Key == 'r'))
10794  {
10795  TTClockResetButton->Click();
10796  }
10797  }
10798  }
10799 
10800 //Track build panel
10801  if((Level1Mode == TrackMode) && TrackBuildPanel->Visible && TrackBuildPanel->Enabled)
10802  {
10803  if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl) && !Shift.Contains(ssAlt))
10804  {
10805  if(AddTrackButton->Visible && AddTrackButton->Enabled && (Key == 'A' || Key == 'a')) //add/remove track elements
10806  {
10807  AddTrackButton->Click();
10808  }
10809  if(SigAspectButton->Visible && SigAspectButton->Enabled && (Key == 'S' || Key == 's')) //cycle through signal aspects
10810  {
10811  SigAspectButton->Click();
10812  }
10813  if(TrackOKButton->Visible && TrackOKButton->Enabled && (Key == 'L' || Key == 'l')) //link track
10814  {
10815  TrackOKButton->Click();
10816  }
10817  if(FontButton->Visible && FontButton->Enabled && (Key == 'F' || Key == 'f')) //change font
10818  {
10819  FontButton->Click();
10820  }
10821  if(LocationNameButton->Visible && LocationNameButton->Enabled && (Key == 'N' || Key == 'n')) //name locations
10822  {
10823  LocationNameButton->Click();
10824  }
10825  if(SetLengthsButton->Visible && SetLengthsButton->Enabled && (Key == 'D' || Key == 'd')) //set distances/speeds
10826  {
10827  SetLengthsButton->Click();
10828  }
10829  if(AddTextButton->Visible && AddTextButton->Enabled && (Key == 'T' || Key == 't')) //add text
10830  {
10831  AddTextButton->Click();
10832  }
10833  if(ScreenGridButton->Visible && ScreenGridButton->Enabled && (Key == 'G' || Key == 'g')) //toggle grid
10834  {
10835  ScreenGridButton->Click();
10836  }
10837  if(MoveTextOrGraphicButton->Visible && MoveTextOrGraphicButton->Enabled && (Key == 'M' || Key == 'm')) //move text or graphic
10838  {
10839  MoveTextOrGraphicButton->Click();
10840  }
10841  if(UserGraphicButton->Visible && UserGraphicButton->Enabled && (Key == 'I' || Key == 'i')) //insert image
10842  {
10843  UserGraphicButton->Click();
10844  }
10845  if(SetGapsButton->Visible && SetGapsButton->Enabled && (Key == 'J' || Key == 'j')) //join gaps
10846  {
10847  SetGapsButton->Click();
10848  }
10849  }
10850  if(Shift.Contains(ssCtrl) && !Shift.Contains(ssShift) && !Shift.Contains(ssAlt))
10851  {
10852  if(SaveRailwayTBPButton->Visible && SaveRailwayTBPButton->Enabled) //save railway in trackbuild mode
10853  {
10854  SaveMenuItem->ShortCut = 0; //It's normally 16467 (Ctrl S) & will be restored in FormKeyUp. Has to be reset or will grab the key combination
10855  if(Key == 'S' || Key == 's')//so this will never execute
10856  {
10857  SaveRailwayTBPButton->Click();
10858  }
10859  }
10860  }
10861  if(!Shift.Contains(ssCtrl) && !Shift.Contains(ssShift) && !Shift.Contains(ssAlt))
10862  {
10863  if((ExitTrackButton->Visible && ExitTrackButton->Enabled) && Key == '\x1b') //escape key
10864  {
10865  ExitTrackButton->Click();
10866  }
10867  }
10868  }
10869 
10870 //PrefDir panel
10871  if(Level1Mode == PrefDirMode && PrefDirPanel->Visible && PrefDirPanel->Enabled && !Shift.Contains(ssAlt))
10872  {
10873  if(!Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
10874  {
10875  if((ExitPrefDirButton->Visible && ExitPrefDirButton->Enabled) && Key == '\x1b') //escape key
10876  {
10877  ExitPrefDirButton->Click();
10878  }
10879  }
10880  if(!Shift.Contains(ssShift) && Shift.Contains(ssCtrl))
10881  {
10882  if(SaveRailwayPDPButton->Visible && SaveRailwayPDPButton->Enabled)
10883  {
10884  SaveMenuItem->ShortCut = 0; //It's normally 16467 (Ctrl S) & will be restored in FormKeyUp. Has to be reset or will grab the key combination
10885  if(Key == 'S' || Key == 's')//so this will never execute
10886  {
10887  SaveRailwayPDPButton->Click();
10888  }
10889  }
10890  }
10891  if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
10892  {
10893  if(AddPrefDirButton->Visible && AddPrefDirButton->Enabled && (Key == 'A' || Key == 'a')) //add pref dir
10894  {
10895  AddPrefDirButton->Click();
10896  }
10897  if(DeleteOnePrefDirButton->Visible && DeleteOnePrefDirButton->Enabled && (Key == 'D' || Key == 'd')) //delete one pref dir
10898  {
10899  DeleteOnePrefDirButton->Click();
10900  }
10901  if(DeleteAllPrefDirButton->Visible && DeleteAllPrefDirButton->Enabled && (Key == 'C' || Key == 'c')) //delete all pref dirs
10902  {
10903  DeleteAllPrefDirButton->Click();
10904  }
10905  }
10906  }
10907 //Note that save button in BaseMode is handled by Ctrl S from the File menu
10908 
10909 //Timetable panel
10910  if(Level1Mode == TimetableMode && TimetablePanel->Visible && TimetablePanel->Enabled && !Shift.Contains(ssAlt))
10911  {
10912  if(!Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
10913  {
10914  if(ExitTTModeButton->Visible && ExitTTModeButton->Enabled && Key == '\x1b') //escape key
10915  {
10916  ExitTTModeButton->Click();
10917  }
10918  }
10919  if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl)) //show/hide timetable edit panel
10920  {
10921  if(ShowHideTTButton->Visible && ShowHideTTButton->Enabled)
10922  {
10923  if(!TimetableEditPanel->Visible)
10924  {
10925  if(Key == 'S' || Key == 's')
10926  {
10927  ShowHideTTButton->Click();
10928  }
10929  }
10930  else if(Key == 'H' || Key == 'h')
10931  {
10932  ShowHideTTButton->Click();
10933  }
10934  }
10935  }
10936  }
10937 
10938 //Timetable edit panel
10939 //These just set flags. The corresponding 'Click()' function executes separately to the keypress because Windows stores the key until after any directly linked key code
10940 //is executed then selects the timetable entry that begins with the letter corresponding to the key. Without this separation the list box is left with the wrong entry
10941 //showing. See DevHistory.txt for the version after v2.4.3 for details.
10942  if(Level1Mode == TimetableMode && TimetableEditPanel->Visible && TimetableEditPanel->Enabled && !Shift.Contains(ssAlt))
10943  {
10944  if(Shift.Contains(ssShift) && !Shift.Contains(ssCtrl))
10945  {
10946  AllEntriesTTListBoxTopPosition = AllEntriesTTListBox->TopIndex; //store value here before the Windows key press function runs (it runs after any local code)
10947  if(PreviousTTEntryButton->Enabled && (Key == 'L' || Key == 'l'))
10948  {
10949  PreviousTTEntryKeyFlag = true;
10950  }
10951  if(NextTTEntryButton->Enabled && (Key == 'N' || Key == 'n'))
10952  {
10953  NextTTEntryKeyFlag = true;
10954  }
10955  if(MoveTTEntryUpButton->Enabled && (Key == 'U' || Key == 'u'))
10956  {
10957  MoveTTEntryUpKeyFlag = true;
10958  }
10959  if(MoveTTEntryDownButton->Enabled && (Key == 'D' || Key == 'd'))
10960  {
10961  MoveTTEntryDownKeyFlag = true;
10962  }
10963  if(CopyTTEntryButton->Enabled && (Key == 'C' || Key == 'c'))
10964  {
10965  CopyTTEntryKeyFlag = true;
10966  }
10967  if(CutTTEntryButton->Enabled && (Key == 'X' || Key == 'x'))
10968  {
10969  CutTTEntryKeyFlag = true;
10970  }
10971  if(PasteTTEntryButton->Enabled && (Key == 'P' || Key == 'p'))
10972  {
10973  PasteTTEntryKeyFlag = true;
10974  }
10975  if(DeleteTTEntryButton->Enabled && (Key == 'E' || Key == 'e'))
10976  {
10977  DeleteTTEntryKeyFlag = true;
10978  }
10979 /* if(SaveTTEntryButton->Enabled && (Key == 'E' || Key == 'e')) //can't have save while editing entry as adds the letter to the entry
10980  {
10981  SaveTTEntryKeyFlag = true;
10982  }
10983  if(CancelTTActionButton->Enabled && (Key == 'K' || Key == 'k')) //can't have cancel while editing entry as adds the letter to the entry
10984  {
10985  CancelTTActionKeyFlag = true;
10986  }
10987 */
10988  if(NewTTEntryButton->Enabled && (Key == 'I' || Key == 'i'))
10989  {
10990  NewTTEntryKeyFlag = true;
10991  }
10992  if(AZOrderButton->Enabled && (Key == 'Z' || Key == 'z'))
10993  {
10994  AZOrderKeyFlag = true;
10995  }
10996 /*
10997  if(AddMinsButton->Enabled && (Key == 'M' || Key == 'm')) //can't have key here as adds the letter to the entry
10998  {
10999  AddMinsKeyFlag = true;
11000  }
11001  if(SubMinsButton->Enabled && (Key == 'B' || Key == 'b')) //can't have key here as adds the letter to the entry
11002  {
11003  SubMinsKeyFlag = true;
11004  }
11005 */
11006  if(TTServiceSyntaxCheckButton->Enabled && (Key == 'Q' || Key == 'q'))
11007  {
11009  }
11010  if(ValidateTimetableButton->Enabled && (Key == 'V' || Key == 'v'))
11011  {
11012  ValidateTimetableKeyFlag = true;
11013  }
11014  if(SaveTTButton->Enabled && (Key == 'T' || Key == 't'))
11015  {
11016  SaveTTKeyFlag = true;
11017  }
11018  if(SaveTTAsButton->Enabled && (Key == 'A' || Key == 'a'))
11019  {
11020  SaveTTAsKeyFlag = true;
11021  }
11022  if(RestoreTTButton->Enabled && (Key == 'R' || Key == 'r'))
11023  {
11024  RestoreTTKeyFlag = true;
11025  }
11026  if(ExportTTButton->Enabled && (Key == 'O' || Key == 'o'))
11027  {
11028  ExportTTKeyFlag = true;
11029  }
11030  if(ConflictAnalysisButton->Enabled && (Key == 'F' || Key == 'f'))
11031  {
11032  ConflictAnalysisKeyFlag = true;
11033  }
11034  }
11035  }
11036 
11037 
11038 //Information menu
11039  if(FloatingInfoMenu->Enabled && !Shift.Contains(ssAlt) && Shift.Contains(ssCtrl) && Shift.Contains(ssShift))
11040  {
11041  if(Key == 'I' || Key == 'i') //toggle track info
11042  {
11043  TrackInfoOnOffMenuItem->Click();
11044  }
11045  else if(TrainInfoMenuItem->Enabled)
11046  {
11047  if(Key == 'S' || Key == 's') //toggle train status info
11048  {
11050  }
11051  else if(Key == 'T' || Key == 't') //toggle train timetable info
11052  {
11053  TrainTTInfoOnOffMenuItem->Click();
11054  }
11055 
11056  }
11057  }
11058 //end of 2.4.2 addition
11059 
11060  }
11061  catch(const Exception &e)
11062  {
11063  ErrorLog(167, e.Message);
11064  }
11065 }
11066 
11067 // ---------------------------------------------------------------------------
11068 
11069 void __fastcall TInterface::FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
11070 {
11071  if((Key != VK_SHIFT) && (Key != VK_CONTROL))
11072  LastNonCtrlOrShiftKeyDown = -1; //reset value to no key down
11073  CtrlKey = false;
11074  ShiftKey = false;
11075  SaveMenuItem->ShortCut = 16467; //restore Ctrl S for save menu in case set to 0 in FormKeyDown
11076 }
11077 
11078 // ---------------------------------------------------------------------------
11079 
11080 void __fastcall TInterface::OutputLog1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11081 {
11082  if((Button == mbRight) && Level2OperMode == Operating)
11083  {
11084  OutputLog1->Caption = "";
11085  }
11086 }
11087 
11088 // ---------------------------------------------------------------------------
11089 
11090 void __fastcall TInterface::OutputLog2MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11091 {
11092  if((Button == mbRight) && Level2OperMode == Operating)
11093  {
11094  OutputLog2->Caption = "";
11095  }
11096 }
11097 // ---------------------------------------------------------------------------
11098 
11099 void __fastcall TInterface::OutputLog3MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11100 {
11101  if((Button == mbRight) && Level2OperMode == Operating)
11102  {
11103  OutputLog3->Caption = "";
11104  }
11105 }
11106 
11107 // ---------------------------------------------------------------------------
11108 
11109 void __fastcall TInterface::OutputLog4MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11110 {
11111  if((Button == mbRight) && Level2OperMode == Operating)
11112  {
11113  OutputLog4->Caption = "";
11114  }
11115 }
11116 
11117 // ---------------------------------------------------------------------------
11118 
11119 void __fastcall TInterface::OutputLog5MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11120 {
11121  if((Button == mbRight) && Level2OperMode == Operating)
11122  {
11123  OutputLog5->Caption = "";
11124  }
11125 }
11126 // ---------------------------------------------------------------------------
11127 
11128 void __fastcall TInterface::OutputLog6MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11129 {
11130  if((Button == mbRight) && Level2OperMode == Operating)
11131  {
11132  OutputLog6->Caption = "";
11133  }
11134 }
11135 
11136 // ---------------------------------------------------------------------------
11137 
11138 void __fastcall TInterface::OutputLog7MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11139 {
11140  if((Button == mbRight) && Level2OperMode == Operating)
11141  {
11142  OutputLog7->Caption = "";
11143  }
11144 }
11145 
11146 // ---------------------------------------------------------------------------
11147 
11148 void __fastcall TInterface::OutputLog8MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11149 {
11150  if((Button == mbRight) && Level2OperMode == Operating)
11151  {
11152  OutputLog8->Caption = "";
11153  }
11154 }
11155 
11156 // ---------------------------------------------------------------------------
11157 
11158 void __fastcall TInterface::OutputLog9MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11159 {
11160  if((Button == mbRight) && Level2OperMode == Operating)
11161  {
11162  OutputLog9->Caption = "";
11163  }
11164 }
11165 
11166 // ---------------------------------------------------------------------------
11167 
11168 void __fastcall TInterface::OutputLog10MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
11169 {
11170  if((Button == mbRight) && Level2OperMode == Operating)
11171  {
11172  OutputLog10->Caption = "";
11173  }
11174 }
11175 
11176 // ---------------------------------------------------------------------------
11177 
11178 void __fastcall TInterface::AboutMenuItemClick(TObject *Sender)
11179 {
11180  try
11181  {
11182  if((Level1Mode == OperMode) && (Level2OperMode != PreStart))
11183  // if PreStart leave as is [Modified at v1.2.0 - formerly just 'if((Level1Mode == OperMode)']
11184  {
11186  SetLevel2OperMode(3);
11187  MasterClock->Enabled = false;
11188  }
11189  AboutForm->ShowModal();
11190  }
11191  catch(const Exception &e)
11192  {
11193  ErrorLog(168, e.Message);
11194  }
11195 }
11196 
11197 // ---------------------------------------------------------------------------
11198 
11199 void __fastcall TInterface::OpenHelpMenuItemClick(TObject *Sender)
11200 {
11201  try
11202  {
11203  // Helpfile allocated during construction of Interface
11204  Application->HelpKeyword(u"Introduction"); // added at v2.0.0 for .chm help file
11205  }
11206  catch(const Exception &e)
11207  {
11208  ErrorLog(175, e.Message);
11209  }
11210 }
11211 
11212 // ---------------------------------------------------------------------------
11213 
11214 void __fastcall TInterface::RailwayWebSiteMenuItemClick(TObject *Sender)
11215 {
11216  const UnicodeString Link = "http://www.railwayoperationsimulator.com";
11217  ::ShellExecute(Handle, NULL, (Link).c_str(), NULL, NULL, SW_SHOWNORMAL);
11218 }
11219 
11220 // ---------------------------------------------------------------------------
11221 
11222 void __fastcall TInterface::BlackBgndMenuItemClick(TObject *Sender)
11223 {
11224  try
11225  {
11226  TrainController->LogEvent("BlackBgndMenuItemClick");
11227  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",BlackBgndMenuItemClick");
11228  TColor OldTransparentColour = Utilities->clTransparent;
11229  Utilities->clTransparent = TColor(0);
11230  SelectBitmap->TransparentColor = Utilities->clTransparent;
11233 
11234  MainScreen->Canvas->Brush->Color = Utilities->clTransparent;
11235  MainScreen->Canvas->FillRect(MainScreen->ClientRect);
11236  Level1Mode = BaseMode;
11237  SetLevel1Mode(128);
11238  Utilities->CallLogPop(1797);
11239  }
11240  catch(const Exception &e)
11241  {
11242  ErrorLog(170, e.Message);
11243  }
11244 }
11245 
11246 // ---------------------------------------------------------------------------
11247 
11248 void __fastcall TInterface::WhiteBgndMenuItemClick(TObject *Sender)
11249 {
11250  try
11251  {
11252  TrainController->LogEvent("WhiteBgndMenuItemClick");
11253  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",WhiteBgndMenuItemClick");
11254  TColor OldTransparentColour = Utilities->clTransparent;
11255  Utilities->clTransparent = TColor(0xFFFFFF);
11256  SelectBitmap->TransparentColor = Utilities->clTransparent;
11259 
11260  MainScreen->Canvas->Brush->Color = Utilities->clTransparent;
11261  MainScreen->Canvas->FillRect(MainScreen->ClientRect);
11262  Level1Mode = BaseMode;
11263  SetLevel1Mode(129);
11264  Utilities->CallLogPop(1798);
11265  }
11266  catch(const Exception &e)
11267  {
11268  ErrorLog(171, e.Message);
11269  }
11270 }
11271 
11272 // ---------------------------------------------------------------------------
11273 
11274 void __fastcall TInterface::BlueBgndMenuItemClick(TObject *Sender)
11275 {
11276  try
11277  {
11278  TrainController->LogEvent("BlueBgndMenuItemClick");
11279  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",BlueBgndMenuItemClick");
11280  TColor OldTransparentColour = Utilities->clTransparent;
11281  Utilities->clTransparent = TColor(0x330000);
11282  SelectBitmap->TransparentColor = Utilities->clTransparent;
11285 
11286  MainScreen->Canvas->Brush->Color = Utilities->clTransparent;
11287  MainScreen->Canvas->FillRect(MainScreen->ClientRect);
11288  Level1Mode = BaseMode;
11289  SetLevel1Mode(130);
11290  Utilities->CallLogPop(1799);
11291  }
11292  catch(const Exception &e)
11293  {
11294  ErrorLog(172, e.Message);
11295  }
11296 }
11297 
11298 // ---------------------------------------------------------------------------
11299 
11300 void __fastcall TInterface::SpeedToggleButtonClick(TObject *Sender)
11301 {
11302  if(SpeedTopLabel->Caption == "mph")
11303  {
11304  SpeedTopLabel->Caption = "km/h";
11305  SpeedBottomLabel->Caption = "mph";
11306  }
11307  else
11308  {
11309  SpeedTopLabel->Caption = "mph";
11310  SpeedBottomLabel->Caption = "km/h";
11311  }
11312  // swap values to match toggle state
11313  UnicodeString SavedTopValue = SpeedEditBox->Text;
11314  UnicodeString SavedBottomValue = SpeedVariableLabel->Caption;
11315 
11316  SpeedEditBox->Text = SavedBottomValue;
11317  SpeedVariableLabel->Caption = SavedTopValue;
11318 }
11319 // ---------------------------------------------------------------------------
11320 
11321 void __fastcall TInterface::SpeedToggleButton2Click(TObject *Sender)
11322 {
11323  if(SpeedTopLabel2->Caption == "mph")
11324  {
11325  SpeedTopLabel2->Caption = "km/h";
11326  SpeedBottomLabel2->Caption = "mph";
11327  }
11328  else
11329  {
11330  SpeedTopLabel2->Caption = "mph";
11331  SpeedBottomLabel2->Caption = "km/h";
11332  }
11333  // swap values to match toggle state
11334  UnicodeString SavedTopValue = SpeedEditBox2->Text;
11335  UnicodeString SavedBottomValue = SpeedVariableLabel2->Caption;
11336 
11337  SpeedEditBox2->Text = SavedBottomValue;
11338  SpeedVariableLabel2->Caption = SavedTopValue;
11339 }
11340 // ---------------------------------------------------------------------------
11341 
11342 void __fastcall TInterface::SpeedEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
11343 {
11344  try
11345  {
11346  TrainController->LogEvent("SpeedEditBoxKeyUp," + AnsiString(Key));
11347  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SpeedEditBoxKeyUp," + AnsiString(Key));
11348  bool ErrorFlag = false, TooBigFlag = false;
11349  if(SpeedEditBox->Text.Length() > 0)
11350  {
11351  if(SpeedEditBox->Text.Length() > 5)
11352  {
11353  TooBigFlag = true;
11354  }
11355  for(int x = 1; x <= SpeedEditBox->Text.Length(); x++)
11356  {
11357  if((SpeedEditBox->Text[x] < '0') || (SpeedEditBox->Text[x] > '9'))
11358  {
11359  SpeedVariableLabel->Caption = "Entry error";
11360  ErrorFlag = true;
11361  break;
11362  }
11363  if(TooBigFlag)
11364  {
11365  SpeedVariableLabel->Caption = "Too big";
11366  break;
11367  }
11368  }
11369  if(!ErrorFlag && !TooBigFlag)
11370  {
11371 /*
11372  1 mph = 1.609344 km/h
11373  1 km/h = 0.621371 mph
11374 */
11375  if(SpeedTopLabel->Caption == "mph")
11376  {
11377  // do mph-to-km/h conversion
11378  int MPH = SpeedEditBox->Text.ToInt();
11379  int KPH = (MPH * 1.609344) + 0.5;
11380  SpeedVariableLabel->Caption = UnicodeString(KPH);
11381  }
11382  else
11383  {
11384  // do km/h-to-mph conversion
11385  int KPH = SpeedEditBox->Text.ToInt();
11386  int MPH = (KPH * 0.621371) + 0.5;
11387  SpeedVariableLabel->Caption = UnicodeString(MPH);
11388  }
11389  }
11390  }
11391  else
11392  {
11393  SpeedVariableLabel->Caption = "";
11394  }
11395  Utilities->CallLogPop(1865);
11396  }
11397  catch(const EConvertError &ec) // thrown for ToInt() conversion error; shouldn't occur but include to prevent a crash
11398  {
11399  SpeedVariableLabel->Caption = "Entry error";
11400  }
11401  catch(const Exception &e)
11402  {
11403  ErrorLog(176, e.Message);
11404  }
11405 }
11406 
11407 // ---------------------------------------------------------------------------
11408 
11409 void __fastcall TInterface::PowerToggleButtonClick(TObject *Sender)
11410 {
11411  if(PowerTopLabel->Caption == "HP")
11412  {
11413  PowerTopLabel->Caption = "kW";
11414  PowerBottomLabel->Caption = "HP";
11415  }
11416  else
11417  {
11418  PowerTopLabel->Caption = "HP";
11419  PowerBottomLabel->Caption = "kW";
11420  }
11421  // swap values to match toggle state
11422  UnicodeString SavedTopValue = PowerEditBox->Text;
11423  UnicodeString SavedBottomValue = PowerVariableLabel->Caption;
11424 
11425  PowerEditBox->Text = SavedBottomValue;
11426  PowerVariableLabel->Caption = SavedTopValue;
11427 }
11428 // ---------------------------------------------------------------------------
11429 
11430 void __fastcall TInterface::PowerEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
11431 {
11432  try
11433  {
11434  TrainController->LogEvent("PowerEditBoxKeyUp," + AnsiString(Key));
11435  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PowerEditBoxKeyUp," + AnsiString(Key));
11436  bool ErrorFlag = false, TooBigFlag = false;
11437  if(PowerEditBox->Text.Length() > 0)
11438  {
11439  if(PowerEditBox->Text.Length() > 8)
11440  {
11441  TooBigFlag = true;
11442  }
11443  for(int x = 1; x <= PowerEditBox->Text.Length(); x++)
11444  {
11445  if((PowerEditBox->Text[x] < '0') || (PowerEditBox->Text[x] > '9'))
11446  {
11447  PowerVariableLabel->Caption = "Entry error";
11448  ErrorFlag = true;
11449  break;
11450  }
11451  if(TooBigFlag)
11452  {
11453  PowerVariableLabel->Caption = "Too big";
11454  break;
11455  }
11456  }
11457  if(!ErrorFlag && !TooBigFlag)
11458  {
11459 /*
11460  1 kW = 1.340482574 HP
11461  1 HP = 0.745699872 kW
11462 */
11463  if(PowerTopLabel->Caption == "HP")
11464  {
11465  // do HP-to-kW conv
11466  int HP = PowerEditBox->Text.ToInt();
11467  int KW = (HP * 0.745699872) + 0.5;
11468  PowerVariableLabel->Caption = UnicodeString(KW);
11469  }
11470  else
11471  {
11472  // do kW-to-HP conv
11473  int KW = PowerEditBox->Text.ToInt();
11474  int HP = (KW * 1.340482574) + 0.5;
11475  PowerVariableLabel->Caption = UnicodeString(HP);
11476  }
11477  }
11478  }
11479  else
11480  {
11481  PowerVariableLabel->Caption = "";
11482  }
11483  Utilities->CallLogPop(1868);
11484  }
11485  catch(const EConvertError &ec) // thrown for ToInt() conversion error; shouldn't occur but include to prevent a crash
11486  {
11487  PowerVariableLabel->Caption = "Entry error";
11488  }
11489  catch(const Exception &e)
11490  {
11491  ErrorLog(179, e.Message);
11492  }
11493 }
11494 // ---------------------------------------------------------------------------
11495 
11496 void __fastcall TInterface::SpeedEditBox2KeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
11497 {
11498  try
11499  {
11500  TrainController->LogEvent("SpeedEditBox2KeyUp," + AnsiString(Key));
11501  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SpeedEditBox2KeyUp," + AnsiString(Key));
11502  bool ErrorFlag = false, TooBigFlag = false;
11503  if(SpeedEditBox2->Text.Length() > 0)
11504  {
11505  if(SpeedEditBox2->Text.Length() > 5)
11506  {
11507  TooBigFlag = true;
11508  }
11509  for(int x = 1; x <= SpeedEditBox2->Text.Length(); x++)
11510  {
11511  if((SpeedEditBox2->Text[x] < '0') || (SpeedEditBox2->Text[x] > '9'))
11512  {
11513  SpeedVariableLabel2->Caption = "Entry error";
11514  ErrorFlag = true;
11515  break;
11516  }
11517  if(TooBigFlag)
11518  {
11519  SpeedVariableLabel2->Caption = "Too big";
11520  break;
11521  }
11522  }
11523  if(!ErrorFlag && !TooBigFlag)
11524  {
11525 /*
11526  1 mph = 1.609344 km/h
11527  1 km/h = 0.621371 mph
11528 */
11529  if(SpeedTopLabel2->Caption == "mph")
11530  {
11531  // do mph-to-km/h conversion
11532  int MPH = SpeedEditBox2->Text.ToInt();
11533  int KPH = (MPH * 1.609344) + 0.5;
11534  SpeedVariableLabel2->Caption = AnsiString(KPH);
11535  }
11536  else
11537  {
11538  // do km/h-to-mph conversion
11539  int KPH = SpeedEditBox2->Text.ToInt();
11540  int MPH = (KPH * 0.621371) + 0.5;
11541  SpeedVariableLabel2->Caption = AnsiString(MPH);
11542  }
11543  }
11544  }
11545  else
11546  {
11547  SpeedVariableLabel2->Caption = "";
11548  }
11549  Utilities->CallLogPop(1866);
11550  }
11551  catch(const EConvertError &ec) // thrown for ToInt() conversion error; shouldn't occur but include to prevent a crash
11552  {
11553  SpeedVariableLabel2->Caption = "Entry error";
11554  }
11555  catch(const Exception &e)
11556  {
11557  ErrorLog(177, e.Message);
11558  }
11559 }
11560 
11561 // ---------------------------------------------------------------------------
11562 
11563 void __fastcall TInterface::LengthEditKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
11564 {
11565  try
11566  {
11567  TrainController->LogEvent("LengthEditKeyUp," + AnsiString(Key));
11568  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",LengthEditKeyUp," + AnsiString(Key));
11569  bool ErrorFlag = false, TooLongFlag = false;
11570  if((MileEdit->Text.Length() > 0) && (MileEdit->Text.Length() < 6))
11571  {
11572  for(int x = 1; x <= MileEdit->Text.Length(); x++)
11573  {
11574  if((MileEdit->Text[x] < '0') || (MileEdit->Text[x] > '9'))
11575  {
11576  MetreVariableLabel->Caption = "Entry error";
11577  ErrorFlag = true;
11578  break;
11579  }
11580  }
11581  }
11582  if((ChainEdit->Text.Length() > 0) && (ChainEdit->Text.Length() < 6))
11583  {
11584  for(int x = 1; x <= ChainEdit->Text.Length(); x++)
11585  {
11586  if((ChainEdit->Text[x] < '0') || (ChainEdit->Text[x] > '9'))
11587  {
11588  MetreVariableLabel->Caption = "Entry error";
11589  ErrorFlag = true;
11590  break;
11591  }
11592  }
11593  }
11594  if((YardEdit->Text.Length() > 0) && (YardEdit->Text.Length() < 6))
11595  {
11596  for(int x = 1; x <= YardEdit->Text.Length(); x++)
11597  {
11598  if((YardEdit->Text[x] < '0') || (YardEdit->Text[x] > '9'))
11599  {
11600  MetreVariableLabel->Caption = "Entry error";
11601  ErrorFlag = true;
11602  break;
11603  }
11604  }
11605  }
11606  if((MileEdit->Text.Length() > 5) || (ChainEdit->Text.Length() > 5) || (YardEdit->Text.Length() > 5))
11607  {
11608  TooLongFlag = true;
11609  MetreVariableLabel->Caption = "Too big";
11610  }
11611  if(!ErrorFlag && !TooLongFlag)
11612  {
11613  int Miles = 0, Chains = 0, Yards = 0, Metres = 0;
11614  if(MileEdit->Text.Length() > 0)
11615  {
11616  Miles = MileEdit->Text.ToInt();
11617  }
11618  if(ChainEdit->Text.Length() > 0)
11619  {
11620  Chains = ChainEdit->Text.ToInt();
11621  }
11622  if(YardEdit->Text.Length() > 0)
11623  {
11624  Yards = YardEdit->Text.ToInt();
11625  }
11626  Metres = int((Miles * 1609.344) + (Chains * 20.1168) + (Yards * 0.9144) + 0.5);
11627  MetreVariableLabel->Caption = AnsiString(Metres);
11628  }
11629  if((MileEdit->Text.Length() == 0) && (ChainEdit->Text.Length() == 0) && (YardEdit->Text.Length() == 0))
11630  {
11631  MetreVariableLabel->Caption = "";
11632  }
11633  Utilities->CallLogPop(1867);
11634  }
11635  catch(const EConvertError &ec) // thrown for ToInt() conversion error; shouldn't occur but include to prevent a crash
11636  {
11637  MetreVariableLabel->Caption = "Entry error";
11638  }
11639  catch(const Exception &e)
11640  {
11641  ErrorLog(178, e.Message);
11642  }
11643 }
11644 
11645 // ---------------------------------------------------------------------------
11646 
11647 void __fastcall TInterface::TTClockAdjButtonClick(TObject *Sender)
11648 {
11649  try
11650  {
11651  TrainController->LogEvent("TTClockAdjButtonClick");
11652  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockAdjButtonClick");
11653 // Utilities->Clock2Stopped = true; // to keep panel buttons disabled, restarted on exit
11654  Display->HideWarningLog(0); //because this panel overwrites it
11655  TTClockAdjPanel->Visible = true;
11656  TTClockAdjButton->Enabled = false;
11657 /*
11658  OperatingPanelLabel->Caption = "Disabled"; all these now dealt with in ClockTimer2
11659  OperatingPanel->Enabled = false;
11660  ZoomButton->Enabled = false;
11661  HomeButton->Enabled = false;
11662  NewHomeButton->Enabled = false;
11663  ScreenLeftButton->Enabled = false;
11664  ScreenRightButton->Enabled = false;
11665  ScreenUpButton->Enabled = false;
11666  ScreenDownButton->Enabled = false;
11667 */
11668  Utilities->CallLogPop(1875);
11669  }
11670  catch(const Exception &e)
11671  {
11672  ErrorLog(181, e.Message);
11673  }
11674 }
11675 
11676 // ---------------------------------------------------------------------------
11677 
11678 void __fastcall TInterface::TTClockExitButtonClick(TObject *Sender)
11679 {
11680  try
11681  {
11682  TrainController->LogEvent("TTClockExitButtonClick");
11683  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockExitButtonClick");
11684  TTClockAdjPanel->Visible = false;
11685  TTClockAdjButton->Enabled = true;
11686 /* these dealt with in ClockTimer2
11687  ZoomButton->Enabled = true;
11688  HomeButton->Enabled = true;
11689  NewHomeButton->Enabled = true;
11690  ScreenLeftButton->Enabled = true;
11691  ScreenRightButton->Enabled = true;
11692  ScreenUpButton->Enabled = true;
11693  ScreenDownButton->Enabled = true;
11694  OperatingPanel->Enabled = true;
11695  OperatingPanelLabel->Caption = "Operation";
11696 */
11697  Display->ShowWarningLog(0);
11698  double TTClockTimeChange = double(TrainController->RestartTime) - PauseEntryRestartTime;
11699  if((TTClockSpeed != PauseEntryTTClockSpeed) || (TTClockTimeChange > 0.000347))
11700  // 30 seconds, min increase is 1 minute & don't trust doubles to stay exactly equal
11702  {
11703  TTClockAdjustWarningPanel->Top = MainScreen->Top + ((MainScreen->Height - TTClockAdjustWarningPanel->Height)/2);
11704  TTClockAdjustWarningPanel->Left = MainScreen->Left + ((MainScreen->Width - TTClockAdjustWarningPanel->Width)/2);
11705  TTClockAdjustWarningLabel->Caption =
11706  "Changes have been made to the timetable clock - you may wish to save a session before resuming operation.\n\nTo cancel all changes re-click the 'Adjust the timetable clock' button then click the reset button BEFORE resuming operation.";
11707  TTClockAdjustWarningPanel->Visible = true;
11708  }
11709 // Utilities->Clock2Stopped = false; // as above
11710  LastNonCtrlOrShiftKeyDown = -1; //to restore the ability to reselect T after adj panel hidden (FormKeyUp doesn't work because the Interface form doesn't have focus)
11711  Utilities->CallLogPop(1876);
11712  }
11713  catch(const Exception &e)
11714  {
11715  ErrorLog(182, e.Message);
11716  }
11717 }
11718 // ---------------------------------------------------------------------------
11719 
11720 void __fastcall TInterface::TTClockx2ButtonClick(TObject *Sender)
11721 {
11722  try
11723  {
11724  TrainController->LogEvent("TTClockx2ButtonClick");
11725  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockx2ButtonClick");
11726  TTClockSpeed = 2;
11727  TTClockSpeedLabel->Caption = "x2";
11729  Utilities->CallLogPop(1878);
11730  }
11731  catch(const Exception &e)
11732  {
11733  ErrorLog(184, e.Message);
11734  }
11735 }
11736 
11737 // ---------------------------------------------------------------------------
11738 
11739 void __fastcall TInterface::TTClockx4ButtonClick(TObject *Sender)
11740 {
11741  try
11742  {
11743  TrainController->LogEvent("TTClockx4ButtonClick");
11744  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockx4ButtonClick");
11745  TTClockSpeed = 4;
11746  TTClockSpeedLabel->Caption = "x4";
11748  Utilities->CallLogPop(1883);
11749  }
11750  catch(const Exception &e)
11751  {
11752  ErrorLog(189, e.Message);
11753  }
11754 }
11755 
11756 // ---------------------------------------------------------------------------
11757 
11758 void __fastcall TInterface::TTClockx8ButtonClick(TObject *Sender)
11759 {
11760  try
11761  {
11762  TrainController->LogEvent("TTClockx8ButtonClick");
11763  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockx8ButtonClick");
11764  TTClockSpeed = 8;
11765  TTClockSpeedLabel->Caption = "x8";
11767  Utilities->CallLogPop(1884);
11768  }
11769  catch(const Exception &e)
11770  {
11771  ErrorLog(190, e.Message);
11772  }
11773 }
11774 
11775 // ---------------------------------------------------------------------------
11776 
11777 void __fastcall TInterface::TTClockx16ButtonClick(TObject *Sender)
11778 {
11779  try
11780  {
11781  TrainController->LogEvent("TTClockx16ButtonClick");
11782  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockx16ButtonClick");
11783  TTClockSpeed = 16;
11784  TTClockSpeedLabel->Caption = "x16";
11786  Utilities->CallLogPop(1885);
11787  }
11788  catch(const Exception &e)
11789  {
11790  ErrorLog(191, e.Message);
11791  }
11792 }
11793 
11794 // ---------------------------------------------------------------------------
11795 
11796 void __fastcall TInterface::TTClockx1ButtonClick(TObject *Sender)
11797 {
11798  try
11799  {
11800  TrainController->LogEvent("TTClockx1ButtonClick");
11801  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockx1ButtonClick");
11802  TTClockSpeed = 1;
11803  TTClockSpeedLabel->Caption = "x1";
11805  Utilities->CallLogPop(1886);
11806  }
11807  catch(const Exception &e)
11808  {
11809  ErrorLog(192, e.Message);
11810  }
11811 }
11812 
11813 // ---------------------------------------------------------------------------
11814 
11815 void __fastcall TInterface::TTClockxHalfButtonClick(TObject *Sender)
11816 {
11817  try
11818  {
11819  TrainController->LogEvent("TTClockxHalfButtonClick");
11820  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockxHalfButtonClick");
11821  TTClockSpeed = 0.5;
11822  TTClockSpeedLabel->Caption = "x1/2";
11824  Utilities->CallLogPop(1887);
11825  }
11826  catch(const Exception &e)
11827  {
11828  ErrorLog(193, e.Message);
11829  }
11830 }
11831 
11832 // ---------------------------------------------------------------------------
11833 
11834 void __fastcall TInterface::TTClockxQuarterButtonClick(TObject *Sender)
11835 {
11836  try
11837  {
11838  TrainController->LogEvent("TTClockxQuarterButtonClick");
11839  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockxQuarterButtonClick");
11840  TTClockSpeed = 0.25;
11841  TTClockSpeedLabel->Caption = "x1/4";
11843  Utilities->CallLogPop(1888);
11844  }
11845  catch(const Exception &e)
11846  {
11847  ErrorLog(194, e.Message);
11848  }
11849 }
11850 
11851 // ---------------------------------------------------------------------------
11852 
11853 void __fastcall TInterface::TTClockxEighthButtonClick(TObject *Sender)
11854 { // added for v2.3.0 for very big railways
11855  try
11856  {
11857  TrainController->LogEvent("TTClockxEighthButtonClick");
11858  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockxEighthButtonClick");
11859  TTClockSpeed = 0.125;
11860  TTClockSpeedLabel->Caption = "x1/8";
11862  Utilities->CallLogPop(2099);
11863  }
11864  catch(const Exception &e)
11865  {
11866  ErrorLog(203, e.Message);
11867  }
11868 }
11869 // ---------------------------------------------------------------------------
11870 
11871 void __fastcall TInterface::TTClockxSixteenthButtonClick(TObject *Sender)
11872 { // added for v2.3.0 for very big railways
11873  try
11874  {
11875  TrainController->LogEvent("TTClockxSixteenthButtonClick");
11876  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockxSixteenthButtonClick");
11877  TTClockSpeed = 0.0625;
11878  TTClockSpeedLabel->Caption = "x1/16";
11880  Utilities->CallLogPop(2100);
11881  }
11882  catch(const Exception &e)
11883  {
11884  ErrorLog(204, e.Message);
11885  }
11886 }
11887 
11888 // ---------------------------------------------------------------------------
11889 
11890 void __fastcall TInterface::TTClockAdd1hButtonClick(TObject *Sender)
11891 {
11892  try
11893  {
11894  TrainController->LogEvent("TTClockAdd1hButtonClick");
11895  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockAdd1hButtonClick");
11896  double TTClockIncrement = 1.0 / 24;
11897  TrainController->RestartTime += TDateTime(TTClockIncrement);
11900  Utilities->CallLogPop(1879);
11901  }
11902  catch(const Exception &e)
11903  {
11904  ErrorLog(185, e.Message);
11905  }
11906 }
11907 
11908 // ---------------------------------------------------------------------------
11909 
11910 void __fastcall TInterface::TTClockAdd10mButtonClick(TObject *Sender)
11911 {
11912  try
11913  {
11914  TrainController->LogEvent("TTClockAdd10mButtonClick");
11915  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockAdd10mButtonClick");
11916  double TTClockIncrement = 1.0 / 144;
11917  TrainController->RestartTime += TDateTime(TTClockIncrement);
11920  Utilities->CallLogPop(1881);
11921  }
11922  catch(const Exception &e)
11923  {
11924  ErrorLog(187, e.Message);
11925  }
11926 }
11927 
11928 // ---------------------------------------------------------------------------
11929 
11930 void __fastcall TInterface::TTClockAdd1mButtonClick(TObject *Sender)
11931 {
11932  try
11933  {
11934  TrainController->LogEvent("TTClockAdd1mButtonClick");
11935  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockAdd1mButtonClick");
11936  double TTClockIncrement = 1.0 / 1440;
11937  TrainController->RestartTime += TDateTime(TTClockIncrement);
11940  Utilities->CallLogPop(1882);
11941  }
11942  catch(const Exception &e)
11943  {
11944  ErrorLog(188, e.Message);
11945  }
11946 }
11947 
11948 // ---------------------------------------------------------------------------
11949 
11950 void __fastcall TInterface::TTClockResetButtonClick(TObject *Sender)
11951 {
11952  try
11953  {
11954  TrainController->LogEvent("TTClockResetButtonClick");
11955  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockResetButtonClick");
11960  if(TTClockSpeed == 2)
11961  TTClockSpeedLabel->Caption = "x2";
11962  else if(TTClockSpeed == 4)
11963  TTClockSpeedLabel->Caption = "x4";
11964  else if(TTClockSpeed == 8)
11965  TTClockSpeedLabel->Caption = "x8";
11966  else if(TTClockSpeed == 16)
11967  TTClockSpeedLabel->Caption = "x16";
11968  else if(TTClockSpeed == 0.5)
11969  TTClockSpeedLabel->Caption = "x1/2";
11970  else if(TTClockSpeed == 0.25)
11971  TTClockSpeedLabel->Caption = "x1/4";
11972  else if(TTClockSpeed == 0.125)
11973  TTClockSpeedLabel->Caption = "x1/8";
11974  else if(TTClockSpeed == 0.0625)
11975  TTClockSpeedLabel->Caption = "x1/16";
11976  else
11977  {
11978  TTClockSpeed = 1;
11979  TTClockSpeedLabel->Caption = "x1";
11980  }
11981  Utilities->CallLogPop(1880);
11982  }
11983  catch(const Exception &e)
11984  {
11985  ErrorLog(186, e.Message);
11986  }
11987 }
11988 
11989 // ---------------------------------------------------------------------------
11990 
11991 void __fastcall TInterface::PresetAutoSigRoutesButtonClick(TObject *Sender)
11992 {
11993  try
11994  {
11995  TrainController->LogEvent("PresetAutoSigRoutesButtonClick");
11996  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",PresetAutoSigRoutesButtonClick");
11997  InfoPanel->Caption = "PRE-START: Presetting automatic signal routes";
11998  OperatingPanelLabel->Caption = "Disabled";
11999  OperatingPanel->Enabled = false; // becomes re-enabled during the call to ClockTimer2
12000  ZoomButton->Enabled = false;
12001  HomeButton->Enabled = false;
12002  NewHomeButton->Enabled = false;
12003  ScreenLeftButton->Enabled = false;
12004  ScreenRightButton->Enabled = false;
12005  ScreenUpButton->Enabled = false;
12006  ScreenDownButton->Enabled = false;
12007 
12008  Screen->Cursor = TCursor(-11); // Hourglass
12009  TPrefDirElement StartElement, EndElement;
12010  bool PointsChanged, AtLeastOneSet = false;
12011  int LastIteratorValue = 0;
12012  while(true)
12013  {
12014  if(!EveryPrefDir->GetStartAndEndPrefDirElements(0, StartElement, EndElement, LastIteratorValue))
12015  break;
12016  // rest of routine here - i.e. build the routes
12017  ConstructRoute->ClearRoute(); // in case not empty though should be
12018  AtLeastOneSet = true;
12019  if(ConstructRoute->GetPreferredRouteStartElement(1, StartElement.HLoc, StartElement.VLoc, EveryPrefDir, true, true))
12020  // true for both ConsecSignalsRoute & AutoSigsFlag
12021  {}
12022  if(ConstructRoute->GetNextPreferredRouteElement(1, EndElement.HLoc, EndElement.VLoc, EveryPrefDir, true, true, ConstructRoute->ReqPosRouteID,
12023  PointsChanged))
12024  {}
12026  }
12027  if(AtLeastOneSet)
12028  {
12031  }
12032  else
12033  {
12034  ShowMessage("No presettable automatic signal routes are available");
12035  }
12036  Screen->Cursor = TCursor(-2); // Arrow
12037  Utilities->CallLogPop(1994);
12038  }
12039  catch(const Exception &e)
12040  {
12041  ErrorLog(195, e.Message);
12042  }
12043 }
12044 
12045 // ---------------------------------------------------------------------------
12046 
12047 void __fastcall TInterface::FormResize(TObject *Sender) // new at v2.1.0
12048 {
12049  try
12050  {
12051  if(!SkipFormResizeEvent) // to avoid calling during startup and especially during shutdown
12052  { // else fails on shutdown because HiddenScreen & other things no longer exist
12053  int DispW = (Interface->Width - 64 - 16) / 16;
12054 // will truncate down to a multiple of 16 (64 = side panels and 16 compensates for excess width of Interface)
12055  int DispH = (Interface->Height - 192) / 16;
12056  MainScreen->Width = DispW * 16;
12057  MainScreen->Height = DispH * 16;
12058  Utilities->ScreenElementWidth = DispW;
12059  Utilities->ScreenElementHeight = DispH;
12060  HiddenScreen->Width = MainScreen->Width;
12061  HiddenScreen->Height = MainScreen->Height;
12062  PerformancePanel->Top = MainScreen->Top + MainScreen->Height - PerformancePanel->Height;
12063  PerformancePanel->Left = MainScreen->Left;
12064  OperatorActionPanel->Top = MainScreen->Top + MainScreen->Height - OperatorActionPanel->Height; // new at v2.2.0
12065  OperatorActionPanel->Left = MainScreen->Left + MainScreen->Width - OperatorActionPanel->Width;
12066  SigImagePanel->Left = (Interface->Width - SigImagePanel->Width) / 2; // added for v2.3.0
12067  DevelopmentPanel->Top = MainScreen->Top + MainScreen->Height - DevelopmentPanel->Height; // new v2.2.0
12068  DevelopmentPanel->Left = MainScreen->Left + MainScreen->Width - DevelopmentPanel->Width; // new v2.2.0
12069  MTBFEditBox->Left = MainScreen->Left + MainScreen->Width - MTBFEditBox->Width + 32; // new v2.4.0 32 is to place it above the positional panel
12070  MTBFLabel->Left = MainScreen->Left + MainScreen->Width - MTBFEditBox->Width + 30 - 55; // new v2.4.0 placed above and to the left of MTBFEditBox
12071  PositionalPanel->Left = MainScreen->Left + MainScreen->Width; // changed at v2.4.0
12072  PositionalPanel->Top = MainScreen->Top; // changed at v2.4.0
12073  PositionalPanel->Height = MainScreen->Height; // changed at v2.4.0
12074 
12075  if(!Display->ZoomOutFlag)
12076  {
12078  }
12079  else
12080  {
12081  Display->ClearDisplay(11);
12083  }
12084  Display->Update();
12085  }
12086  }
12087  catch(const Exception &e)
12088  {
12089  ErrorLog(197, e.Message);
12090  }
12091 }
12092 
12093 // ---------------------------------------------------------------------------
12094 
12095 void __fastcall TInterface::OperatorActionButtonClick(TObject *Sender)
12096 {
12097  try
12098  {
12099  TrainController->LogEvent("OperatorActionButtonClick");
12100  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",OperatorActionButtonClick");
12102  {
12103  ShowOperatorActionPanel = true;
12104  OperatorActionPanel->Visible = true;
12106  OperatorActionButton->Glyph->LoadFromResourceName(0, "HideOpActionPanel");
12107  }
12108  else
12109  {
12110  ShowOperatorActionPanel = false;
12111  OperatorActionPanel->Visible = false;
12113  OperatorActionButton->Glyph->LoadFromResourceName(0, "ShowOpActionPanel");
12114  }
12115  Utilities->CallLogPop(2073);
12116  }
12117  catch(const Exception &e)
12118  {
12119  ErrorLog(199, e.Message);
12120  }
12121 }
12122 
12123 // ---------------------------------------------------------------------------
12124 
12126 {
12127  try
12128  {
12129  TrainController->LogEvent("ConverttoRightHandSignalsMenuItemClick");
12130  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ConverttoRightHandSignalsMenuItemClick");
12132  if(Utilities->RHSignalFlag) // RH sigs after conversion
12133  {
12134  ConverttoRightHandSignalsMenuItem->Caption = "Convert to Left Hand Signals";
12136  {
12138  }
12139  else
12140  {
12142  }
12143  SigImagePanel->Caption = "Signals will be on the right hand side of the track";
12144  SigsOnLeftImage1->Visible = false;
12145  SigsOnLeftImage2->Visible = false;
12146  SigsOnRightImage1->Visible = true;
12147  SigsOnRightImage2->Visible = true;
12148  std::ofstream SigFile((CurDir + "\\Signal.hnd").c_str());
12149  if(SigFile.fail())
12150  {
12151  ShowMessage("Failed to store right hand signal setting, program will default to left hand signals when next loaded");
12152  }
12153  else
12154  {
12155  Utilities->SaveFileString(SigFile, "RHSignals");
12156  }
12157  }
12158  else // LH sigs after conversion
12159  {
12160  ConverttoRightHandSignalsMenuItem->Caption = "Convert to Right Hand Signals";
12162  {
12164  }
12165  else
12166  {
12168  }
12169  SigImagePanel->Caption = "Signals will be on the left hand side of the track";
12170  SigsOnRightImage1->Visible = false;
12171  SigsOnRightImage2->Visible = false;
12172  SigsOnLeftImage1->Visible = true;
12173  SigsOnLeftImage2->Visible = true;
12174  std::ofstream SigFile((CurDir + "\\Signal.hnd").c_str());
12175  if(SigFile.fail())
12176  {
12177  // no need for message as will default to LH: ShowMessage("Failed to store left hand signal setting, program will default to left hand signals when next loaded");
12178  }
12179  else
12180  {
12181  Utilities->SaveFileString(SigFile, "LHSignals");
12182  }
12183  }
12184  Utilities->CallLogPop(2097);
12185  }
12186  catch(const Exception &e)
12187  {
12188  ErrorLog(202, e.Message);
12189  }
12190 }
12191 // ---------------------------------------------------------------------------
12192 
12193 void __fastcall TInterface::MTBFEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
12194 
12195 {
12196  try
12197  {
12198  TrainController->LogEvent("MTBFEditBoxKeyUp," + AnsiString(Key));
12199  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MTBFEditBoxKeyUp," + AnsiString(Key));
12200  if((Level1Mode != OperMode) || (Level2OperMode != PreStart))
12201  {
12202  Utilities->CallLogPop(2160);
12203  return;
12204  }
12205  bool TooBigFlag = false, BadCharsFlag = false;
12208  if(MTBFEditBox->Text.Length() > 0)
12209  {
12210  for(int x = 1; x <= MTBFEditBox->Text.Length(); x++)
12211  {
12212  if((MTBFEditBox->Text[x] < '0') || (MTBFEditBox->Text[x] > '9'))
12213  {
12214  BadCharsFlag = true;
12215  break;
12216  }
12217  }
12218  if(!BadCharsFlag)
12219  {
12220  if(StrToInt(MTBFEditBox->Text) > 10000)
12221  {
12222  TooBigFlag = true;
12223  }
12224  }
12225  if(TooBigFlag)
12226  {
12227  ShowMessage("Maximum value allowed is 10,000");
12228  MTBFEditBox->Text = "";
12231  Utilities->CallLogPop(2161);
12232  return;
12233  }
12234  if(BadCharsFlag)
12235  {
12236  ShowMessage("Value must be a whole number with no special characters");
12237  MTBFEditBox->Text = "";
12240  Utilities->CallLogPop(2162);
12241  return;
12242  }
12243  TrainController->AvHoursIntValue = StrToInt(MTBFEditBox->Text); // ok if user enters 0 as that means no failures
12245  }
12247  {
12248  MTBFEditBox->Text = "";
12250  }
12251  Utilities->CallLogPop(2163);
12252  }
12253  catch(const Exception &e)
12254  {
12255  ErrorLog(209, e.Message);
12256  }
12257 }
12258 
12259 // ---------------------------------------------------------------------------
12260 
12261 void __fastcall TInterface::MTBFEditBoxClick(TObject *Sender)
12262 {
12263  try
12264  {
12265  TrainController->LogEvent("MTBFEditBoxClick");
12266  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MTBFEditBoxClick");
12267  if((Level1Mode != OperMode) || (Level2OperMode != PreStart))
12268  {
12269  MTBFEditBox->ReadOnly = true; // it should be anyway but include here for safety
12271  "Values can only be entered or changed in Pre-Start mode\ni.e. after selecting 'Operate railway' but before clicking 'Run'");
12272  }
12273  Utilities->CallLogPop(2164);
12274  }
12275  catch(const Exception &e)
12276  {
12277  ErrorLog(210, e.Message);
12278  }
12279 }
12280 
12281 // ---------------------------------------------------------------------------
12282 
12283 void __fastcall TInterface::UserGraphicButtonClick(TObject *Sender)
12284 {
12285  try
12286  {
12287  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",MTBFEditBoxClick");
12288  LengthConversionPanel->Visible = false;
12289  SpeedConversionPanel->Visible = false;
12290  DistanceKey->Visible = false;
12291  TrackElementPanel->Visible = false;
12292  SigAspectButton->Enabled = false;
12294  SetLevel2TrackMode(63);
12295  Display->Update();
12296  if((SelectedGraphicFileName != "") && (!Track->UserGraphicVector.empty())) //latter condition added at v2.6.0 because showed after ClearAll & reselect failed
12297  {
12298  UserGraphicReselectPanel->Visible = true;
12299  }
12300  else
12301  {
12302  UserGraphicReselectPanel->Visible = false;
12303  LoadUserGraphic(0);
12304  }
12305  Utilities->CallLogPop(2183);
12306  }
12307  catch(const Exception &e)
12308  {
12309  ErrorLog(212, e.Message);
12310  }
12311 }
12312 
12313 // ---------------------------------------------------------------------------
12314 
12315 void __fastcall TInterface::ReselectUserGraphicClick(TObject *Sender)
12316 {
12317  try
12318  {
12319  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ReselectUserGraphicClick");
12320  TrainController->LogEvent("ReselectUserGraphicClick " + SelectedGraphicFileName);
12321  UserGraphicReselectPanel->Visible = false;
12322  TTrack::TUserGraphicMap::iterator UGMIt = Track->UserGraphicMap.find(SelectedGraphicFileName);
12323  if(UGMIt == Track->UserGraphicMap.end())
12324  {
12325  ShowMessage("Unable to find graphic file " + SelectedGraphicFileName + ". Check it still exists.");
12326  Utilities->CallLogPop(2196);
12327  return;
12328  }
12330  SetLevel2TrackMode(64);
12331  Utilities->CallLogPop(2184);
12332  }
12333  catch(const Exception &e)
12334  {
12335  ErrorLog(213, e.Message);
12336  }
12337 }
12338 // ---------------------------------------------------------------------------
12339 
12340 void __fastcall TInterface::SelectNewGraphicClick(TObject *Sender)
12341 {
12342  try
12343  {
12344  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",SelectNewGraphicClick");
12345  UserGraphicReselectPanel->Visible = false;
12346  LoadUserGraphic(1);
12347  Utilities->CallLogPop(2185);
12348  }
12349  catch(const Exception &e)
12350  {
12351  ErrorLog(214, e.Message);
12352  }
12353 }
12354 
12355 // ---------------------------------------------------------------------------
12356 
12357 void __fastcall TInterface::TTClockAdjustOKButtonClick(TObject *Sender)
12358 {
12359  try
12360  {
12361  TrainController->LogEvent("TTClockAdjustOKButtonClick");
12362  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",TTClockAdjustOKButtonClick");
12363  TTClockAdjustWarningPanel->Visible = false;
12364  if(TTClockAdjustCheckBox->Checked)
12365  {
12366  TTClockAdjustWarningHide = true;
12367  }
12368  Utilities->CallLogPop(2219);
12369  }
12370  catch(const Exception &e)
12371  {
12372  ErrorLog(216, e.Message);
12373  }
12374 }
12375 
12376 //---------------------------------------------------------------------------
12377 
12378 void __fastcall TInterface::ConflictAnalysisButtonClick(TObject *Sender)
12379 {
12380  try
12381  {
12382  TrainController->LogEvent("ConflictAnalysisButtonClick");
12383  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",ConflictAnalysisButtonClick");
12384  ConflictPanel->Visible = true;
12385  Utilities->CallLogPop(2220);
12386  }
12387  catch(const Exception &e)
12388  {
12389  ErrorLog(217, e.Message);
12390  }
12391 }
12392 
12393 //---------------------------------------------------------------------------
12394 
12395 void __fastcall TInterface::CPCancelButtonClick(TObject *Sender)
12396 {
12397  try
12398  {
12399  TrainController->LogEvent("CPCancelButtonClick");
12400  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CPCancelButtonClick");
12401  ConflictPanel->Visible = false;
12402  Utilities->CallLogPop(2221);
12403  }
12404  catch(const Exception &e)
12405  {
12406  ErrorLog(218, e.Message);
12407  }
12408 }
12409 
12410 //---------------------------------------------------------------------------
12411 
12412 void __fastcall TInterface::CPGenFileButtonClick(TObject *Sender)
12413 {
12414  try
12415  {
12416  TrainController->LogEvent("CPGenFileButtonClick");
12417  Utilities->CallLog.push_back(Utilities->TimeStamp() + ",CPGenFileButtonClick");
12418  if(!CPArrivalsCheckBox->Checked && !CPDeparturesCheckBox->Checked && !CPAtLocCheckBox->Checked)
12419  {
12420  ShowMessage("No boxes ticked!");
12421  }
12422  else //keep ticks & range values from last time, only reset on startup
12423  {
12424  Screen->Cursor = TCursor(-11);//hourglass
12425  AnsiString TTTitle;
12427  {
12428  for(int x = CreateEditTTFileName.Length(); x > 0; x--) // first need to strip out the timetable title from the full name
12429  {
12430  if(CreateEditTTFileName[x] == '\\')
12431  {
12432  TTTitle = CreateEditTTFileName.SubString(x + 1, CreateEditTTFileName.Length() - x - 4);
12433  break;
12434  }
12435  }
12437  CPAtLocCheckBox->Checked, CPEditArrRange->Text.ToInt(), CPEditDepRange->Text.ToInt()))
12438  {
12439  ShowMessage("Analysis complete and file created");
12440  }
12441  ConflictPanel->Visible = false;
12442  }
12443  }
12444  Screen->Cursor = TCursor(-2);//arrow
12445  Utilities->CallLogPop(2222);
12446  }
12447  catch(const Exception &e)
12448  {
12449  ErrorLog(219, e.Message);
12450  }
12451 }
12452 
12453 //---------------------------------------------------------------------------
12454 // end of fastcalls & directly associated functions
12455 // ---------------------------------------------------------------------------
12456 
12457 void TInterface::SetTopIndex(int Caller)
12458 {
12459 //Set TopIndex to the proper value & also Selected so don't have a different selection to the highlighted entry
12460  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetTopIndex");
12461  if((TTCurrentEntryPtr - TimetableEditVector.begin()) < AllEntriesTTListBox->TopIndex)
12462  {
12464  }
12465  else if((TTCurrentEntryPtr - TimetableEditVector.begin()) > (AllEntriesTTListBox->TopIndex + 45))
12466  {
12467  AllEntriesTTListBox->TopIndex = TTCurrentEntryPtr - TimetableEditVector.begin() - 45;
12468  }
12469  else
12470  {
12471  AllEntriesTTListBox->TopIndex = AllEntriesTTListBox->TopIndex;
12472  }
12473  AllEntriesTTListBox->Selected[TTCurrentEntryPtr - TimetableEditVector.begin()] = true;
12474  Utilities->CallLogPop(2207);
12475 }
12476 
12477 // ---------------------------------------------------------------------------
12478 
12479 void TInterface::ClearandRebuildRailway(int Caller) // now uses HiddenScreen to help avoid flicker
12480 {
12481  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ClearandRebuildRailway");
12482  bool ClockState = Utilities->Clock2Stopped;
12483 
12484  Utilities->Clock2Stopped = true;
12486  Track->RebuildUserGraphics(0, HiddenDisplay); // new at v2.4.0, plot first so all else overwrites, including the grid if selected
12487  if(ScreenGridFlag && (Level1Mode == TrackMode))
12488  {
12489  int WidthNum = int(MainScreen->Width / 160) + 1;
12490  int HeightNum = int(MainScreen->Height / 144) + 1;
12491  for(int x = 0; x < WidthNum; x++)
12492  {
12493  for(int y = 0; y < HeightNum; y++)
12494  {
12495  HiddenDisplay->PlotAbsolute(0, x * 160, y * 144, RailGraphics->GridBitmap);
12496  }
12497  }
12498  }
12499 
12500 // TextHandler->RebuildFromTextVector(1, HiddenDisplay); //This now incorporated in RebuildTrackAndText so that text is plotted after inactive
12501 // elements but before active elements. This is so text can overwite stations and non-station named locations.
12502 
12504 
12505 // Display->Output->Invalidate(); experiment, needs TDisplay Output to be public. Trying to invoke the white flashes that
12506 // used to occur frequently without Disp->Update() in PlotOriginal
12507 
12508  // OperMode LCs plotted below
12510  {
12512  }
12513 
12514  if(Level1Mode == PrefDirMode)
12515  {
12516  if(EveryPrefDir->PrefDirSize() > 0)
12517  {
12519  }
12521  {
12523  }
12524  }
12525 
12526  if(Level1Mode == TrackMode)
12527  {
12529  {
12530  LocationNameButton->Enabled = true;
12531  }
12532  else
12533  {
12534  LocationNameButton->Enabled = false;
12535  }
12536  }
12537 
12539  {
12541  DistanceKey->Visible = true;
12542  DistancesMarked = true;
12543  LengthConversionPanel->Visible = true;
12544  SpeedConversionPanel->Visible = true;
12545  }
12546 
12547  if(Level2TrackMode == DistanceContinuing) // for extended distances
12548  {
12549  if(ConstructPrefDir->PrefDirSize() > 0)
12550  {
12551  Track->LengthMarker(2, HiddenDisplay); //this line was after the next line until v2.5.1, changed so magenta not overrridden after PrefDirMarker called
12553  DistanceKey->Visible = true;
12554  DistancesMarked = true;
12555  LengthConversionPanel->Visible = true;
12556  SpeedConversionPanel->Visible = true;
12557  }
12558  }
12559 
12561  // this is to keep the distance markers if they are already present when Select is chosen, in case user wishes to choose SelectLengths,
12562  // don't need to display ConstructPrefDir marker as that only needed in DistanceContinuing mode
12563  {
12565  DistanceKey->Visible = true;
12566  }
12567 
12569  // cancel DistancesMarked if exit from any of these modes
12570  {
12571  DistancesMarked = false;
12572  DistanceKey->Visible = false;
12573  LengthConversionPanel->Visible = false; // added at v1.3.1 to remove when distance/speed setting exited
12574  SpeedConversionPanel->Visible = false; // added at v1.3.1 to remove when distance/speed setting exited
12575  }
12576 
12578  // in process of moving so use NewSelectBitmapHLoc & VLoc
12579  {
12581  }
12582 
12584  // not in process of moving or failed to click mouse within selection so use SelectBitmapHLoc & VLoc
12585  {
12587  }
12588 
12589  if(Level1Mode == OperMode)
12590  {
12592  if(!AllRoutes->LockedRouteVector.empty())
12593  {
12594  for(TAllRoutes::TLockedRouteVectorIterator LRVIT = AllRoutes->LockedRouteVector.end() - 1; LRVIT >= AllRoutes->LockedRouteVector.begin(); LRVIT--)
12595  {
12596  if(!(AllRoutes->TrackIsInARoute(7, LRVIT->LastTrackVectorPosition, LRVIT->LastXLinkPos)))
12597  {
12598  AllRoutes->LockedRouteVector.erase(LRVIT);
12599  // if end element not in route then a train must have entered it from the wrong end and erased the whole route,
12600  // hence no longer needed so get rid of it (end of route can't be points, crossover or bridge so danger of
12601  // route being on the other track of a 2-track element doesn't arise)
12602  continue;
12603  }
12604  TOneRoute Route = AllRoutes->GetFixedRouteAt(0, LRVIT->RouteNumber);
12605  int x = Route.PrefDirSize() - 1;
12606  bool BreakFlag = false;
12607  TPrefDirElement PrefDirElement = Route.GetFixedPrefDirElementAt(1, x);
12608  while(PrefDirElement.GetTrackVectorPosition() != LRVIT->TruncateTrackVectorPosition)
12609  {
12610  HiddenDisplay->PlotOutput(10, (PrefDirElement.HLoc) * 16, (PrefDirElement.VLoc) * 16,
12611  RailGraphics->LockedRouteCancelPtr[PrefDirElement.GetELink()]);
12612  if(!(AllRoutes->TrackIsInARoute(8, PrefDirElement.Conn[PrefDirElement.GetELinkPos()],
12613  PrefDirElement.ConnLinkPos[PrefDirElement.GetELinkPos()])))
12614  {
12615  BreakFlag = true;
12616  break; // train removed earlier element from route so stop here
12617  }
12618  x--;
12619  if(x < 0) //added after Albie Vowles reported error on 14/08/20 by email
12620  { //it means that part of the route (including that at the truncate point) has been cancelled, in this case by a train running past the signal
12621  BreakFlag = true; //at danger and cancelling the route elements in front of it. The locked route is now too short and this 'while' loop won't find
12622  break; //it, so x keeps decrementing and when it becomes -1 an error is thrown. This addition prevents the error.
12623  }
12624  PrefDirElement = Route.GetFixedPrefDirElementAt(2, x);
12625  }
12626  if(!BreakFlag)
12627  {
12628  if(PrefDirElement.GetTrackVectorPosition() == LRVIT->TruncateTrackVectorPosition)
12629  {
12630  HiddenDisplay->PlotOutput(11, (PrefDirElement.HLoc) * 16, (PrefDirElement.VLoc) * 16,
12631  RailGraphics->LockedRouteCancelPtr[PrefDirElement.GetELink()]);
12632  }
12633  }
12634  }
12635  }
12636 
12637  if(RouteMode == RouteContinuing)
12638  {
12640 // system thinks overlay is already plotted, so plot original to reset the OverlayPlotted flag
12643  if(AutoSigsFlag)
12645  else if(ConsecSignalsRoute)
12647  else
12649  }
12650 
12651  if(Track->PointFlashFlag)
12652  {
12653  // need to reset the screen location for picking up the original graphic
12654  int Left, Top; // Embarcadero change - these missing in error from Borland file
12656  // note that the above Pos values are wrt layout, not the screen, but the Left & Top values are wrt screen
12657  PointFlash->SetSourceRect(Left, Top);
12658  PointFlash->LoadOriginalScreenGraphic(4); // reload from new position
12659  // doesn't matter whether Flash was on or off when this function called as will sort itself out later (may miss a flash but won't be noticeable)
12660  }
12661 
12662  // now plot level crossings (must be after routes). These don't need any base elements to be plotted as they are already plotted.
12663  // In order to avoid plotting the whole LC for every element of a LC a bool value - LCPlotted - is used to save time
12664  for(unsigned int x = 0; x < Track->LCVector.size(); x++)
12665  {
12666  (Track->InactiveTrackVector.begin() + (*(Track->LCVector.begin() + x)))->LCPlotted = false;
12667  }
12668  for(unsigned int x = 0; x < Track->LCVector.size(); x++)
12669  {
12670  int BaseSpeedTag;
12671  TTrackElement ATE;
12672  TTrackElement ITE = *(Track->InactiveTrackVector.begin() + (*(Track->LCVector.begin() + x)));
12673  {
12674  BaseSpeedTag = Track->GetTrackElementFromTrackMap(0, ITE.HLoc, ITE.VLoc).SpeedTag;
12675  if(ITE.LCPlotted == false)
12676  {
12677  if(ITE.Attribute == 0)
12678  {
12680  }
12681  else if(ITE.Attribute == 1)
12682  {
12683  //need to determine if should plot green (manual) or red (auto), but all linked LCs have ConsecSignals set to 2 in BarriersDownVector if manual
12684  //so just need to test this for the HLoc & VLoc position match
12685  for(unsigned int x = 0; x < Track->BarriersDownVector.size(); x++)
12686  {
12687  if((Track->BarriersDownVector.at(x).HLoc == ITE.HLoc) && (Track->BarriersDownVector.at(x).VLoc == ITE.VLoc))
12688  {
12689  if(Track->BarriersDownVector.at(x).ConsecSignals == 2)
12690  {
12691  Track->PlotPlainLoweredLinkedLevelCrossingBarriersAndSetMarkers(0, BaseSpeedTag, ITE.HLoc, ITE.VLoc, HiddenDisplay, true); //true for manual = green
12692  }
12693  else
12694  {
12695  Track->PlotPlainLoweredLinkedLevelCrossingBarriersAndSetMarkers(1, BaseSpeedTag, ITE.HLoc, ITE.VLoc, HiddenDisplay, false); //false for auto = red
12696  }
12697  }
12698  }
12699  }
12700  // if ITE->Attribute == 2 then LC is changing, FlashingGraphics will take care of flashing & final plotting,
12701  // it won't set LCPlotted but no real time lost in this case
12702  }
12703  }}
12705  }
12706 
12707  Display->ZoomOutFlag = false;
12708  ZoomButton->Glyph->LoadFromResourceName(0, "ZoomOut");
12709  MainScreen->Picture->Bitmap->Assign(HiddenScreen->Picture->Bitmap);
12710  Display->Update(); // resurrected when Update() dropped from PlotOutput etc
12711  Utilities->Clock2Stopped = ClockState;
12712  Utilities->CallLogPop(91);
12713 }
12714 
12715 // ---------------------------------------------------------------------------
12716 
12717 bool TInterface::HighLightOneGap(int Caller, int &HLoc, int &VLoc)
12718 {
12719  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",HighLightOneGap");
12720  if(Track->FindAndHighlightAnUnsetGap(1)) // true if find one
12721  {
12722  if(!PreventGapOffsetResetting) // don't reset display position if returning from zoomout mode
12723  {
12724  while((Display->DisplayOffsetH - Track->GetGapHLoc()) > 0)
12725  Display->DisplayOffsetH -= (Utilities->ScreenElementWidth / 2); // use 30 instead of 60 so less likely to appear behind the message box
12728  while((Display->DisplayOffsetV - Track->GetGapVLoc()) > 0)
12729  Display->DisplayOffsetV -= (Utilities->ScreenElementHeight / 2); // use 18 instead of 36 so less likely to appear behind the message box
12732  }
12733  InfoPanel->Visible = true;
12734  InfoPanel->Caption = "CONNECTING GAPS: Click on connecting element";
12735  ClearandRebuildRailway(31); // get rid of earlier gap selection
12736  Utilities->CallLogPop(92);
12737  return true; // return as one now identified & over to MainScreenMouseDown with Level2TrackMode = GapSetting
12738  }
12739  Utilities->CallLogPop(93);
12740  return false; // no unset ones left to find
12741 }
12742 
12743 // ---------------------------------------------------------------------------
12744 
12746 {
12747  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ClearEverything");
12748  if(FileChangedFlag)
12749  {
12750  UnicodeString MessageStr = "The railway has changed, close it without saving?";
12751  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
12752  if(button == IDNO)
12753  {
12754  Utilities->CallLogPop(1140);
12755  return false;
12756  }
12757  }
12758  Display->ClearDisplay(7);
12760 
12761  Display->DisplayOffsetH = 0;
12762  Display->DisplayOffsetV = 0;
12767 
12768 // these ensure that all persistent vectors, maps & multimaps etc are cleared
12769  delete TrainController;
12770  delete EveryPrefDir;
12771  delete ConstructRoute;
12772  delete ConstructPrefDir;
12773  delete AllRoutes;
12774  delete Track;
12775  delete TextHandler;
12776 // NB can't delete & recreate Utilities or will lose the CallLog file & have errors due to log being empty when try to
12777 // pop earlier pushed values
12778 // OK though as no containers in Utilities that need to clear & PerformanceFile recreated when begin to operate a later
12779 // railway
12780  TextHandler = new TTextHandler;
12781  Track = new TTrack;
12782  AllRoutes = new TAllRoutes;
12784  ConstructRoute = new TOneRoute;
12785  EveryPrefDir = new TOnePrefDir;
12787  PerformanceLogBox->Lines->Clear();
12788  ResetAll(1);
12789  Utilities->CallLogPop(94);
12790  return true;
12791 }
12792 
12793 // ---------------------------------------------------------------------------
12794 
12795 bool TInterface::FileIntegrityCheck(int Caller, char *FileName) const // true for success
12796 {
12797  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",FileIntegrityCheck," + AnsiString(FileName));
12798  std::ifstream VecFile(FileName);
12799 
12800  if(VecFile.is_open())
12801  {
12802  if(!Utilities->CheckFileStringZeroDelimiter(VecFile)) // Program version
12803  {
12804  VecFile.close();
12805  Utilities->CallLogPop(1805);
12806  return false;
12807  }
12808  if(!Utilities->CheckFileInt(VecFile, -1000000, 1000000)) // DisplayOffsetHHome
12809  {
12810  VecFile.close();
12811  Utilities->CallLogPop(1440);
12812  return false;
12813  }
12814  if(!Utilities->CheckFileInt(VecFile, -1000000, 1000000)) // DisplayOffsetVHome
12815  {
12816  VecFile.close();
12817  Utilities->CallLogPop(1441);
12818  return false;
12819  }
12820  bool GraphicsFollow = false;
12821  int NumberOfActiveElements;
12822  if(!(Track->CheckTrackElementsInFile(1, NumberOfActiveElements, GraphicsFollow, VecFile))) // for new loads
12823  {
12824  VecFile.close();
12825  Utilities->CallLogPop(95);
12826  return false;
12827  }
12828  if(!(TextHandler->CheckTextElementsInFile(0, VecFile)))
12829  {
12830  VecFile.close();
12831  Utilities->CallLogPop(96);
12832  return false;
12833  }
12834  if(!(EveryPrefDir->CheckOnePrefDir(0, NumberOfActiveElements, VecFile)))
12835  {
12836  VecFile.close();
12837  Utilities->CallLogPop(97);
12838  return false;
12839  }
12840  if(GraphicsFollow)
12841  {
12842  if(!Track->CheckUserGraphics(0, VecFile, CurDir + "\\" + USERGRAPHICS_DIR_NAME)) // include path to Graphics folder
12843  {
12844  VecFile.close();
12845  Utilities->CallLogPop(2186);
12846  return false;
12847  }
12848  }
12849  VecFile.close();
12850  }
12851  else
12852  {
12853  Utilities->CallLogPop(1153);
12854  return false;
12855  }
12856  Utilities->CallLogPop(98);
12857  return true;
12858 }
12859 
12860 // ---------------------------------------------------------------------------
12861 
12862 void TInterface::Delay(int Caller, double Msec)
12863 {
12864  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",Delay," + AnsiString(Msec));
12865  TDateTime First, Second;
12866  bool Finished = false;
12867 
12868  First = TDateTime::CurrentDateTime();
12869  double TimeVal1 = 86400000 * double(First); // no of msec in a day
12870 
12871  while(!Finished)
12872  {
12873  Second = TDateTime::CurrentDateTime();
12874  double TimeVal2 = 86400000 * double(Second);
12875  if((TimeVal2 - TimeVal1) > Msec)
12876  Finished = true;
12877  }
12878  Utilities->CallLogPop(1203);
12879 }
12880 
12881 // ---------------------------------------------------------------------------
12882 
12884 {
12885  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ResetCurrentSpeedButton");
12886  if(CurrentSpeedButton)
12887  CurrentSpeedButton->Down = false;
12888  CurrentSpeedButton = 0;
12889  Utilities->CallLogPop(1204);
12890 }
12891 
12892 // ---------------------------------------------------------------------------
12893 
12895 {
12896  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",MovingTrainPresentOnFlashingRoute");
12897  int TrainID;
12898 
12899  if(ConstructRoute->SearchVectorSize() == 0)
12900  {
12901  Utilities->CallLogPop(99);
12902  return false;
12903  }
12904  for(unsigned int x = 0; x < ConstructRoute->SearchVectorSize(); x++)
12905  {
12906  TPrefDirElement PrefDirElement = ConstructRoute->GetFixedSearchElementAt(14, x);
12907  if(PrefDirElement.TrackType == Bridge)
12908  {
12909  if(PrefDirElement.GetXLinkPos() < 2)
12910  TrainID = Track->TrackElementAt(486, PrefDirElement.GetTrackVectorPosition()).TrainIDOnBridgeTrackPos01;
12911  else
12912  TrainID = Track->TrackElementAt(487, PrefDirElement.GetTrackVectorPosition()).TrainIDOnBridgeTrackPos23;
12913  }
12914  else
12915  TrainID = Track->TrackElementAt(488, PrefDirElement.GetTrackVectorPosition()).TrainIDOnElement;
12916  if((TrainID > -1) && !(TrainController->TrainVectorAtIdent(4, TrainID).Stopped()))
12917  {
12918  Utilities->CallLogPop(100);
12919  return true;
12920  }
12921  // check for crossed diagonal fouling by train added at v1.2.0
12922  int TrainID; // not used
12923  int LinkNumber1 = PrefDirElement.Link[PrefDirElement.GetELinkPos()];
12924  int LinkNumber2 = PrefDirElement.Link[PrefDirElement.GetXLinkPos()];
12925  if((LinkNumber1 == 1) || (LinkNumber1 == 3) || (LinkNumber1 == 7) || (LinkNumber1 == 9))
12926  {
12927  if(Track->DiagonalFouledByTrain(1, PrefDirElement.HLoc, PrefDirElement.VLoc, LinkNumber1, TrainID))
12928  {
12929  Utilities->CallLogPop(2037);
12930  return true;
12931  }
12932  }
12933  if((LinkNumber2 == 1) || (LinkNumber2 == 3) || (LinkNumber2 == 7) || (LinkNumber2 == 9))
12934  {
12935  if(Track->DiagonalFouledByTrain(2, PrefDirElement.HLoc, PrefDirElement.VLoc, LinkNumber2, TrainID))
12936  {
12937  Utilities->CallLogPop(2038);
12938  return true;
12939  }
12940  }
12941  }
12942  Utilities->CallLogPop(101);
12943  return false;
12944 }
12945 
12946 // ---------------------------------------------------------------------------
12947 
12949 {
12950  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",RevertToOriginalRouteSelector");
12951  AutoRouteStartMarker->PlotOriginal(26, Display); // if overlay not plotted will ignore
12952  SigRouteStartMarker->PlotOriginal(27, Display); // if overlay not plotted will ignore
12953  NonSigRouteStartMarker->PlotOriginal(28, Display); // if overlay not plotted will ignore
12954  RouteCancelFlag = false;
12956  {
12957  RouteCancelButton->Enabled = true;
12958  }
12959  else
12960  {
12961  RouteCancelButton->Enabled = false;
12962  }
12965 // reset here so that a n element that has been selected and then not doesn't remain set as a single element
12966  InfoPanel->Visible = true;
12967  if(Level2OperMode != Paused)
12968  {
12969  InfoPanel->Caption = InfoCaptionStore;
12970  }
12971  Utilities->CallLogPop(102);
12972 }
12973 
12974 // ---------------------------------------------------------------------------
12975 
12976 // usermode functions below
12978 {
12979  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetLevel1Mode");
12980  if(!Display->ZoomOutFlag)
12981  {
12984  Track->GapFlashFlag = false;
12985  }
12986 // GapFlash resets when any mode selected unless zoomed out
12987 // note that if selecting zoom back in then this will be called before ZoomOutFlag is reset so won't
12988 // reset GapFlashFlag
12989  switch(Level1Mode) // use the data member
12990  {
12991  case BaseMode:
12992  CopyMenuItem->ShortCut = TextToShortCut(""); // added these for v2.1.0 to set default values after use of the 'Edit' menu during track building
12993  CutMenuItem->ShortCut = TextToShortCut(""); // to allow normal cutting/copying/pasting, especially in timetable construction or editing
12994  PasteMenuItem->ShortCut = TextToShortCut("");
12999  LengthConversionPanel->Visible = false;
13000  SpeedConversionPanel->Visible = false;
13001  TimetableEditPanel->Visible = false;
13002  TrainController->TTEditPanelVisible = false; //added at v2.6.0 for two location message
13003  TrackBuildPanel->Visible = false;
13004  TrackElementPanel->Visible = false;
13005  LocationNameTextBox->Visible = false;
13006  TextBox->Visible = false;
13007  TrackLengthPanel->Visible = false;
13008  InfoPanel->Visible = false;
13009  PrefDirPanel->Visible = false;
13010  TimetablePanel->Visible = false;
13011  OperatingPanel->Visible = false;
13012  PrefDirKey->Visible = false;
13013  TrackLinkedImage->Visible = false;
13014  TrackNotLinkedImage->Visible = false;
13015  GapsSetImage->Visible = false;
13016  GapsNotSetImage->Visible = false;
13017  LocationNamesSetImage->Visible = false;
13018  LocationNamesNotSetImage->Visible = false;
13019  ModeMenu->Enabled = true;
13020  FileMenu->Enabled = true;
13021  EditMenu->Enabled = false;
13022  BuildTrackMenuItem->Enabled = true;
13023  SigAspectButton->Enabled = false;
13024  Track->ChangingLCVector.clear();
13025  Track->BarriersDownVector.clear();
13027  ConverttoRightHandSignalsMenuItem->Enabled = false; // new at v2.3.0
13028  SigImagePanel->Visible = false; // new at v2.3.0
13029  MTBFEditBox->Visible = false; // new at v2.4.0
13030  MTBFLabel->Visible = false;
13031  TTClockAdjustWarningPanel->Visible = false;
13032  if(Track->IsTrackFinished())
13033  {
13034  PlanPrefDirsMenuItem->Enabled = true;
13035  if(TimetableTitle != "")
13036  {
13037  OperateRailwayMenuItem->Enabled = true;
13038  }
13039  else
13040  {
13041  OperateRailwayMenuItem->Enabled = false;
13042  }
13043  }
13044  else
13045  {
13046  PlanPrefDirsMenuItem->Enabled = false;
13047  OperateRailwayMenuItem->Enabled = false;
13048  }
13049  if(RlyFile)
13050  {
13051  LoadTimetableMenuItem->Enabled = true;
13052  }
13053  else
13054  {
13055  LoadTimetableMenuItem->Enabled = false;
13056  }
13057  LoadRailwayMenuItem->Enabled = true;
13058  if(NoRailway())
13059  {
13060  SaveAsMenuItem->Enabled = false;
13061  ImageMenu->Enabled = false;
13062  SaveImageAndGridMenuItem->Enabled = false;
13063  SaveImageNoGridMenuItem->Enabled = false;
13064  SaveImageAndPrefDirsMenuItem->Enabled = false;
13065  SaveOperatingImageMenuItem->Enabled = false;
13066  BlackBgndMenuItem->Enabled = false;
13067  WhiteBgndMenuItem->Enabled = false;
13068  BlueBgndMenuItem->Enabled = false;
13069  ConverttoRightHandSignalsMenuItem->Enabled = true; // new at v2.3.0
13070  SigImagePanel->Visible = true; // new at v2.3.0
13071  if(Utilities->clTransparent != TColor(0))
13072  {
13073  BlackBgndMenuItem->Enabled = true;
13074  }
13075  if(Utilities->clTransparent != TColor(0xFFFFFF))
13076  {
13077  WhiteBgndMenuItem->Enabled = true;
13078  }
13079  if(Utilities->clTransparent != TColor(0x330000))
13080  {
13081  BlueBgndMenuItem->Enabled = true;
13082  }
13083  ClearAllMenuItem->Enabled = false;
13084  InfoPanel->Visible = true;
13085  InfoPanel->Caption = "Select an option from the File, Mode or Help menus";
13086  }
13087  else
13088  {
13089  InfoPanel->Visible = false;
13090  SaveAsMenuItem->Enabled = true;
13091  ImageMenu->Enabled = true;
13092  SaveImageAndGridMenuItem->Enabled = true;
13093  SaveImageNoGridMenuItem->Enabled = true;
13094  if(EveryPrefDir->PrefDirSize() > 0)
13095  SaveImageAndPrefDirsMenuItem->Enabled = true;
13096  else
13097  SaveImageAndPrefDirsMenuItem->Enabled = false;
13098  BlackBgndMenuItem->Enabled = false;
13099  WhiteBgndMenuItem->Enabled = false;
13100  BlueBgndMenuItem->Enabled = false;
13101  SaveOperatingImageMenuItem->Enabled = false;
13102  ClearAllMenuItem->Enabled = true;
13103  }
13104  if(SavedFileName == "")
13105  {
13106  SaveMenuItem->Enabled = false;
13107  }
13108  else if(!FileChangedFlag)
13109  {
13110  SaveMenuItem->Enabled = false;
13111  }
13112  else if((SavedFileName[SavedFileName.Length()] == 'y') || (SavedFileName[SavedFileName.Length()] == 'Y')) // 'rly' file
13113  {
13114  if(!(Track->IsReadyForOperation(false)))
13115  {
13116  SaveMenuItem->Enabled = false; // can't save under its old name as not now a .rly file
13117  }
13118  else
13119  {
13120  SaveMenuItem->Enabled = true; // must have changed some of the PrefDirs (because FileChangedFlag is true)
13121  }
13122  }
13123  else
13124  {
13125  SaveMenuItem->Enabled = true;
13126  }
13127  LoadSessionMenuItem->Enabled = true;
13128  ExitMenuItem->Enabled = true;
13129  ScreenGridFlag = false;
13130  TrainController->CrashWarning = false;
13131  TrainController->DerailWarning = false;
13132  TrainController->SPADWarning = false;
13134  TrainController->CallOnWarning = false;
13137  UserGraphicReselectPanel->Visible = false;
13138  ClearandRebuildRailway(32); // to get rid of unwanted displays (eg distance markers)
13139  SetTrackBuildImages(13);
13140  break;
13141 
13142  case TimetableMode:
13146  ModeMenu->Enabled = false;
13147  SigImagePanel->Visible = false; // new at v2.3.0
13148  FileMenu->Enabled = false;
13149  EditMenu->Enabled = false;
13150  FloatingInfoMenu->Enabled = false;
13151  ImageMenu->Enabled = false;
13152  TimetableEditPanel->BringToFront();
13153  TimetableHandler();
13154  break;
13155 
13156  case TrackMode:
13157  if(Level2TrackMode == CutMoving)
13158  {
13159  Level2TrackMode = Pasting; // paste the selection
13160  SetLevel2TrackMode(52);
13161  }
13166  TrackBuildPanel->Visible = true;
13167  TrackBuildPanelLabel->Caption = "Build/modify";
13168  TrackElementPanel->Visible = false;
13169  TrackLengthPanel->Visible = false;
13170  PrefDirPanel->Visible = false;
13171  TimetablePanel->Visible = false;
13172  OperatingPanel->Visible = false;
13173  InfoPanel->Visible = false;
13174  InfoPanel->Caption = "";
13175  LocationNameTextBox->Visible = false;
13176  TextBox->Visible = false;
13177  ModeMenu->Enabled = false;
13178  SigImagePanel->Visible = false; // new at v2.3.0
13179  FileMenu->Enabled = false;
13180  // set edit menu items
13182  // track buttons
13183  AddTrackButton->Enabled = true;
13185  {
13186  LocationNameButton->Enabled = true;
13187  }
13188  else
13189  {
13190  LocationNameButton->Enabled = false;
13191  }
13192  ScreenGridButton->Enabled = true;
13193  ExitTrackButton->Enabled = true;
13194  SetGapsButton->Enabled = false;
13195  TrackOKButton->Enabled = false;
13196  if(Track->GapsUnset(5))
13197  {
13198  SetGapsButton->Enabled = true;
13199  }
13200  // only enable if there are gaps still to be set (returns false for no track)
13201  else
13202  {
13203  if(!(Track->NoActiveTrack(2)) && !(Track->IsTrackFinished()))
13204  {
13205  TrackOKButton->Enabled = true;
13206  }
13207  // TrackOK only enabled if track exists, there are no unset gaps, and track not finished
13208  }
13209  SetLengthsButton->Enabled = false;
13210  if(Track->IsTrackFinished()) // can only set lengths for several elements together if TrackFinished
13211  {
13212  SetLengthsButton->Enabled = true;
13213  }
13214  // text buttons
13215  AddTextButton->Enabled = true;
13216  TextOrUserGraphicGridButton->Enabled = true;
13217  FontButton->Enabled = true;
13218  MoveTextOrGraphicButton->Enabled = false;
13219  if(TextHandler->TextVectorSize(9) > 0)
13220  {
13221  MoveTextOrGraphicButton->Enabled = true;
13222  }
13223  if(!Track->UserGraphicVector.empty())
13224  {
13225  MoveTextOrGraphicButton->Enabled = true;
13226  }
13227  SelectionValid = false;
13229  TimetableTitle = "";
13230  SetCaption(0);
13231  break;
13232 
13233  case PrefDirMode:
13237  PrefDirPanel->Visible = true;
13238  PrefDirPanelLabel->Caption = "Preferred direction selection";
13239 
13240  InfoPanel->Visible = true;
13241  InfoPanel->Caption = "PREFERRED DIRECTION SETTING: Select preferred direction start location (right click to erase)";
13242  PrefDirKey->Visible = true;
13243  ModeMenu->Enabled = false;
13244  SigImagePanel->Visible = false; // new at v2.3.0
13245  FileMenu->Enabled = false;
13246 // set edit menu items
13248  AddPrefDirButton->Enabled = false;
13249  DeleteOnePrefDirButton->Enabled = false;
13251  if(EveryPrefDir->PrefDirSize() > 0)
13252  {
13253  DeleteAllPrefDirButton->Visible = true;
13254  DeleteAllPrefDirButton->Enabled = true;
13255  SaveImageAndPrefDirsMenuItem->Enabled = true;
13256  }
13257  else
13258  {
13259  DeleteAllPrefDirButton->Enabled = false;
13260  SaveImageAndPrefDirsMenuItem->Enabled = false;
13261  }
13262  ExitPrefDirButton->Enabled = true;
13263  ClearandRebuildRailway(33); // to mark PrefDirs & clear earlier PrefDir markers
13264 // TimetableTitle = ""; no need to unload timetable if only PrefDirs being changed
13265 // SetCaption();
13266  break;
13267 
13268  case OperMode: // if there are any PrefDirs, set to SigPref, else to NoSigNonPref; start in Paused mode
13272  OperatingPanel->Visible = true;
13273  OperatingPanelLabel->Caption = "Operation";
13274 
13275  CallingOnButton->Visible = false;
13276  PresetAutoSigRoutesButton->Visible = true;
13277  PresetAutoSigRoutesButton->Enabled = true;
13278  InfoPanel->Visible = true;
13279  SigImagePanel->Visible = false; // new at v2.3.0
13280  ModeMenu->Enabled = false;
13281  FileMenu->Enabled = false;
13282  EditMenu->Enabled = false;
13283  ImageMenu->Enabled = true;
13284  SaveImageAndGridMenuItem->Enabled = true;
13285  SaveImageNoGridMenuItem->Enabled = true;
13286  if(EveryPrefDir->PrefDirSize() > 0)
13287  SaveImageAndPrefDirsMenuItem->Enabled = true;
13288  else
13289  SaveImageAndPrefDirsMenuItem->Enabled = false;
13290  SaveOperatingImageMenuItem->Enabled = true;
13291  AutoSigsFlag = false;
13292  MTBFEditBox->Visible = true; // visible at pre-start whether any value set or not, so can set a value if required
13294  {
13295  MTBFEditBox->Text = AnsiString(TrainController->AvHoursIntValue);
13296  }
13297  else
13298  {
13299  MTBFEditBox->Text = "";
13300  }
13301  MTBFEditBox->ReadOnly = false; // because this is prestart mode
13302  MTBFLabel->Visible = true;
13303  MTBFLabel->Caption = "Mean time between\ntrain failures in\ntimetable hours";
13305  if(EveryPrefDir->PrefDirSize() > 0)
13306  {
13307  ConsecSignalsRoute = true;
13308  PreferredRoute = true;
13309  }
13310  else // no PrefDirs
13311  {
13312  ConsecSignalsRoute = false;
13313  PreferredRoute = false;
13314  }
13315 
13316  OperateButton->Enabled = true;
13317  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
13318  ExitOperationButton->Enabled = true;
13319  TTClockAdjButton->Enabled = true;
13320  ShowPerformancePanel = false;
13321  PerformanceLogButton->Glyph->LoadFromResourceName(0, "ShowLog");
13322  ShowOperatorActionPanel = false; // new at v2.2.0
13323  OperatorActionButton->Glyph->LoadFromResourceName(0, "ShowOpActionPanel"); // new v2.2.0
13324 
13326 
13327  Utilities->Clock2Stopped = false;
13331  TTClockSpeed = 1;
13332  TTClockSpeedLabel->Caption = "x1";
13335 
13336  PerformanceFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
13337  // format "16/06/2009 20:55:17"
13338  // avoid characters in filename:= / \ : * ? " < > |
13339  PerformanceFileName = CurDir + "\\" + PERFLOG_DIR_NAME + "\\Log " + PerformanceFileName + "; " + RailwayTitle + "; " + TimetableTitle + ".txt";
13340 
13341  Utilities->PerformanceFile.open(PerformanceFileName.c_str(), std::ios_base::out);
13342  if(Utilities->PerformanceFile.fail())
13343  {
13344  ShowMessage("Performance logfile failed to open, logs won't be saved. Ensure that there is a folder named " + PERFLOG_DIR_NAME +
13345  " in the folder where the 'Railway.exe' program file resides");
13346  }
13348 // DisableRouteButtons(2); enable route setting or pre-start
13349 // DisablePanelsStoreMainMenuStates();
13350  TrainController->ContinuationAutoSigVector.clear(); // for restarting after earlier run
13351  AllRoutes->LockedRouteVector.clear(); // for restarting after earlier run
13352 // TrainController->Operate(1);//plot trains that are present at TT start time, ready for running - no, allow route plotting prior to train entries
13353 
13354 // reset all performance indicators
13378 
13379  TrainController->OpActionPanelHintDelayCounter = 0; // new at v2.2.0 to reset hint delay
13380  OAListBox->Clear();
13381  OAListBox->Items->Add(L""); // hints for OpActionPanel
13382  OAListBox->Items->Add(L"");
13383  OAListBox->Items->Add(L"");
13384  OAListBox->Items->Add(L"Left click");
13385  OAListBox->Items->Add(L"headcode");
13386  OAListBox->Items->Add(L"to locate train");
13387  OAListBox->Items->Add(L"");
13388  OAListBox->Items->Add(L"");
13389  OAListBox->Items->Add(L"");
13390  OAListBox->Items->Add(L"");
13391  OAListBox->Items->Add(L"Left click and");
13392  OAListBox->Items->Add(L"hold grey area");
13393  OAListBox->Items->Add(L"to move panel");
13394 
13395  ClearandRebuildRailway(55); // so points display with one fillet
13396  break;
13397 
13398  case RestartSessionOperMode: // restart in Paused mode after a session load, sets both Level1Mode & Level2OperMode
13399  Level1Mode = OperMode;
13400 // Level2OperMode = Paused; this is now loaded during LoadInterface & could be PreStart of Paused
13403  OperatingPanel->Visible = true;
13404  OperatingPanelLabel->Caption = "Operation";
13405 
13406  CallingOnButton->Visible = true;
13407  PresetAutoSigRoutesButton->Visible = false;
13408  InfoPanel->Visible = true;
13409  ModeMenu->Enabled = false;
13410  SigImagePanel->Visible = false; // new at v2.3.0
13411  FileMenu->Enabled = false;
13412  EditMenu->Enabled = false;
13413  ImageMenu->Enabled = true;
13414  SaveImageAndGridMenuItem->Enabled = true;
13415  SaveImageNoGridMenuItem->Enabled = true;
13416  if(EveryPrefDir->PrefDirSize() > 0)
13417  SaveImageAndPrefDirsMenuItem->Enabled = true;
13418  else
13419  SaveImageAndPrefDirsMenuItem->Enabled = false;
13420  SaveOperatingImageMenuItem->Enabled = true;
13421 
13422  OperateButton->Enabled = true;
13423  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
13424  ExitOperationButton->Enabled = true;
13425  TTClockAdjButton->Enabled = true;
13428  if(Level2OperMode == Paused)
13429  DisableRouteButtons(3); // could be PreStart or Paused
13434  TTClockSpeed = 1;
13435  TTClockSpeedLabel->Caption = "x1";
13437  ShowPerformancePanel = false; // added at v2.2.0
13438  ShowOperatorActionPanel = false; // new at v2.2.0
13439  TrainController->OpActionPanelHintDelayCounter = 0; // new at v2.2.0 to reset hint delay
13440  OAListBox->Clear();
13441  OAListBox->Items->Add(L""); // hints for OpActionPanel
13442  OAListBox->Items->Add(L"");
13443  OAListBox->Items->Add(L"");
13444  OAListBox->Items->Add(L"Left click");
13445  OAListBox->Items->Add(L"headcode");
13446  OAListBox->Items->Add(L"to locate train");
13447  OAListBox->Items->Add(L"");
13448  OAListBox->Items->Add(L"");
13449  OAListBox->Items->Add(L"");
13450  OAListBox->Items->Add(L"");
13451  OAListBox->Items->Add(L"Left click and");
13452  OAListBox->Items->Add(L"hold grey area");
13453  OAListBox->Items->Add(L"to move panel");
13454  if((TrainController->AvHoursIntValue > 0) || (Level2OperMode == PreStart)) // only visible if already set or if still in prestart mode
13455  {
13456  MTBFEditBox->Visible = true;
13458  {
13459  MTBFEditBox->Text = AnsiString(TrainController->AvHoursIntValue);
13460  }
13461  else
13462  {
13463  MTBFEditBox->Text = "";
13464  }
13465  MTBFEditBox->ReadOnly = false; // because this is still prestart mode
13466  MTBFLabel->Visible = true;
13467  MTBFLabel->Caption = "Mean time between\ntrain failures in\ntimetable hours";
13469  }
13470  else
13471  {
13472  MTBFEditBox->Visible = false;
13473  MTBFEditBox->Text = "";
13474  MTBFEditBox->ReadOnly = true; // because this is not prestart mode
13475  MTBFLabel->Visible = false;
13476  MTBFLabel->Caption = "Mean time between\ntrain failures in\ntimetable hours";
13478  }
13479  break;
13480 
13481  default:
13482  // No further recursion in BaseMode so OK
13483  Level1Mode = BaseMode;
13484  SetLevel1Mode(29);
13485  break;
13486  }
13487  Utilities->CallLogPop(103);
13488 }
13489 
13490 // ---------------------------------------------------------------------------
13491 
13493 {
13494  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetLevel2TrackMode");
13495  if(Level1Mode != TrackMode)
13496  {
13497  // No further recursion in BaseMode so OK
13498  Level1Mode = BaseMode;
13499  SetLevel1Mode(20);
13500  Utilities->CallLogPop(1115);
13501  return;
13502  }
13504  {
13505  Utilities->CallLogPop(104);
13506  return;
13507  }
13508  switch(Level2TrackMode) // use the data member
13509  {
13510  case AddTrack:
13512  InfoPanel->Visible = true;
13513  InfoPanel->Caption = "ADDING TRACK: Select element then left click to add it. Right click an element to remove it.";
13514  LengthConversionPanel->Visible = false; // in case had been in distance setting mode
13515  SpeedConversionPanel->Visible = false; // in case had been in distance setting mode
13516  TrackElementPanel->Visible = true;
13517  TrackElementPanel->Enabled = true;
13518  SigAspectButton->Visible = true;
13519  SigAspectButton->Enabled = true;
13520  ClearandRebuildRailway(34); // to replot grid if required & clear any other unwanted items
13522  SetLengthsButton->Enabled = false;
13523  if(Track->IsTrackFinished()) // can only set lengths for several elements together if TrackFinished
13524  {
13525  SetLengthsButton->Enabled = true;
13526  }
13527  UserGraphicReselectPanel->Visible = false;
13528  SelectLengthsFlag = false; // in case still set though probably won't be
13529  EditMenu->Enabled = true; //added at v2.6.0 to allow edits for an empty screen so track elements can fill a selected area
13530  break;
13531 
13532  case AddGraphic:
13533  InfoPanel->Visible = true;
13534  InfoPanel->Caption = "ADDING GRAPHIC: Left click layout to add SELECTED graphic, right click to remove ANY graphic.";
13535  break;
13536 
13537  case SelectGraphic:
13538  InfoPanel->Visible = true;
13539  InfoPanel->Caption = "SELECTING USER GRAPHIC: Select the graphic file then add as many as necessary to the layout.";
13540  break;
13541 
13542  case GapSetting:
13543  int HLoc, VLoc, Count;
13544  Count = Track->NumberOfGaps(0);
13545  if(div(Count, 2).rem == 1) // condition OK
13546  {
13547  ShowMessage("Can't connect, there are an odd number of gaps");
13549  SetLevel1Mode(77);
13551  // No further recursion in AddTrack so OK
13552  SetLevel2TrackMode(40);
13553  Utilities->CallLogPop(105);
13554  return;
13555  }
13556  if(!HighLightOneGap(2, HLoc, VLoc)) // condition OK
13557  // need to call this here to start gap setting process off,
13558  // called in MainScreenMouseDown hereafter. Function returns false for either a LocError (links not yet
13559  // complete) or no more gaps to be highlighted
13560  {
13561  // shouldn't reach here as later gaps covered in MainScreenMouseDown but leave & give error message
13562  ShowMessage("Error - Even number of gaps but all set after first call to HighLightOneGap");
13564  SetLevel1Mode(78);
13566  // No further recursion in AddTrack so OK
13567  SetLevel2TrackMode(41);
13568  Utilities->CallLogPop(106);
13569  return; // all gaps set
13570  }
13571  InfoPanel->Visible = true;
13572  InfoPanel->Caption = "CONNECTING GAPS: Click on connecting gap";
13573  UserGraphicReselectPanel->Visible = false;
13575  break;
13576 
13577  case AddText:
13578  InfoPanel->Visible = true;
13579  InfoPanel->Caption = "ADDING/EDITING TEXT: Left click to add, right click first letter to erase, or left click first letter to edit)";
13580  if(TextHandler->TextVectorSize(13) > 0)
13581  {
13582  MoveTextOrGraphicButton->Enabled = true;
13583  }
13584  else
13585  {
13586  MoveTextOrGraphicButton->Enabled = false;
13587  }
13588  UserGraphicReselectPanel->Visible = false;
13589  ClearandRebuildRailway(58); // to drop DistanceKey if was displayed
13590  break;
13591 
13592  case MoveTextOrGraphic:
13593  InfoPanel->Visible = true;
13594  InfoPanel->Caption = "MOVING TEXT OR GRAPHIC: If text left click first letter, if graphic left click anywhere, then drag";
13595  UserGraphicReselectPanel->Visible = false;
13596  ClearandRebuildRailway(59); // to drop DistanceKey if was displayed
13597  break;
13598 
13599  case AddLocationName:
13600  InfoPanel->Visible = true;
13601  InfoPanel->Caption = "NAMING LOCATIONS: Click on location element to add or change name";
13602  ClearandRebuildRailway(35); // to get rid of earlier red rectangle
13603  UserGraphicReselectPanel->Visible = false;
13604  SetTrackBuildImages(12);
13605  break;
13606 
13607  case DistanceStart:
13608  InfoPanel->Visible = true;
13609  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Select first location (only non-default elements marked)";
13610  DistanceKey->Visible = true;
13611  LengthConversionPanel->Visible = true;
13612  SpeedConversionPanel->Visible = true;
13613  UserGraphicReselectPanel->Visible = false;
13614  ClearandRebuildRailway(36); // to get rid of earlier unwanted markings
13615  break;
13616 
13617  case DistanceContinuing:
13618  InfoPanel->Visible = true;
13619  if(ConstructPrefDir->PrefDirSize() == 1)
13620  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Select next location";
13621  else
13622  InfoPanel->Caption = "DISTANCE/SPEED SETTING: Continue or set values (overall length), or right click to cancel/truncate";
13623  UserGraphicReselectPanel->Visible = false;
13624  ClearandRebuildRailway(54); // to remove earlier end marker if present
13625  break;
13626 
13627  case TrackSelecting:
13628  Track->CopyFlag = false;
13629  if(!SelectionValid)
13630  ResetSelectRect(); // so a viewpoint change before a new SelectRect chosen doesn't redisplay
13631  // the old SelectRect (only called when entered from SelectMenuItemClick, & not from
13632  // ReselectMenuItemClick)
13633  InfoPanel->Visible = true;
13634  InfoPanel->Caption = "SELECTING: Select area - click left mouse && drag";
13635  SelectMenuItem->Enabled = false;
13636  ReselectMenuItem->Enabled = false;
13637  CancelSelectionMenuItem->Enabled = true;
13638  UserGraphicReselectPanel->Visible = false;
13639  break;
13640 
13641  case CopyMoving:
13642  Track->CopyFlag = true;
13643  InfoPanel->Visible = true;
13644  InfoPanel->Caption = "COPYING: Left click in selection && drag";
13645  CutMenuItem->Enabled = false;
13646  CopyMenuItem->Enabled = false;
13647  FlipMenuItem->Enabled = false;
13648  MirrorMenuItem->Enabled = false;
13649  RotRightMenuItem->Enabled = false;
13650  RotLeftMenuItem->Enabled = false;
13651  RotateMenuItem->Enabled = false;
13652  PasteMenuItem->Enabled = true;
13653 // PasteWithAttributesMenuItem->Enabled = false; //new at v2.2.0 - don't allow the option if copying
13654  DeleteMenuItem->Enabled = false;
13655  SelectLengthsMenuItem->Enabled = false;
13656  SelectBiDirPrefDirsMenuItem->Visible = false;
13657  CancelSelectionMenuItem->Enabled = false;
13661  UserGraphicReselectPanel->Visible = false;
13662  break;
13663 
13664  case CutMoving:
13665  { // have to use braces as otherwise the default case bypasses the initialisation of these local variables
13666  // erase track elements within selected region
13667  Track->CopyFlag = false;
13668  bool EraseSuccessfulFlag, NeedToLink = false, TextChangesMade = false, GraphicChangesMade = false; ;
13669  int ErasedTrackVectorPosition;
13670  Screen->Cursor = TCursor(-11); // Hourglass;
13671  InfoPanel->Visible = true;
13672  InfoPanel->Caption = "CUT PROCESSING: Please do not click the mouse";
13673  InfoPanel->Update();
13674  for(int H = SelectRect.left; H < SelectRect.right; H++)
13675  {
13676  for(int V = SelectRect.top; V < SelectRect.bottom; V++)
13677  {
13678  Track->EraseTrackElement(2, H, V, ErasedTrackVectorPosition, EraseSuccessfulFlag, false);
13679  if(EraseSuccessfulFlag)
13680  {
13681  if(ErasedTrackVectorPosition > -1)
13682  EveryPrefDir->RealignAfterTrackErase(1, ErasedTrackVectorPosition);
13683  NeedToLink = true;
13684  }
13685  }
13686  }
13687  // erase text elements within selected region
13688  int LowSelectHPos = SelectRect.left * 16;
13689  int HighSelectHPos = SelectRect.right * 16;
13690  int LowSelectVPos = SelectRect.top * 16;
13691  int HighSelectVPos = SelectRect.bottom * 16;
13692  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
13693  {
13694  for(TTextHandler::TTextVectorIterator TextPtr = (TextHandler->TextVector.end() - 1); TextPtr >= TextHandler->TextVector.begin();
13695  TextPtr--) // reverse to prevent skipping during erase
13696  {
13697  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
13698  HighSelectVPos))
13699  {
13700  if(TextHandler->TextErase(1, TextPtr->HPos, TextPtr->VPos, AnsiString("")))
13701  {;
13702  } // unused condition
13703  TextChangesMade = true;
13704  }
13705  }
13706  }
13707  // erase graphic elements that fall wholly within region to be overwritten
13708  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
13709  {
13710  for(TTrack::TUserGraphicVector::iterator GraphicPtr = (Track->UserGraphicVector.end() - 1); GraphicPtr >= Track->UserGraphicVector.begin();
13711  GraphicPtr--) // reverse to prevent skipping during erase
13712  {
13713  if((GraphicPtr->HPos >= LowSelectHPos) && ((GraphicPtr->HPos + GraphicPtr->Width) < HighSelectHPos) && (GraphicPtr->VPos >= LowSelectVPos)
13714  && ((GraphicPtr->VPos + GraphicPtr->Height) < HighSelectVPos))
13715  {
13716  Track->UserGraphicVector.erase(GraphicPtr);
13717  GraphicChangesMade = true;
13718  }
13719  }
13720  }
13721  Track->CheckMapAndTrack(11); // test
13722  Track->CheckMapAndInactiveTrack(10); // test
13723  Track->CheckLocationNameMultiMap(19); // test
13724  Screen->Cursor = TCursor(-2); // Arrow;
13725  // Track->SetTrackFinished(!NeedToLink); This is an error (see Sam Wainwright email of 24/08/17 & devhistory.txt
13726  // if track not linked to begin with then becomes linked if NeedToLink false
13727  if(NeedToLink)
13728  Track->SetTrackFinished(false); // corrected for v2.1.0
13729  InfoPanel->Caption = "CUTTING: Left click in selection && drag";
13730  CutMenuItem->Enabled = false;
13731  CopyMenuItem->Enabled = false;
13732  FlipMenuItem->Enabled = false;
13733  MirrorMenuItem->Enabled = false;
13734  RotRightMenuItem->Enabled = false;
13735  RotLeftMenuItem->Enabled = false;
13736  RotateMenuItem->Enabled = false;
13737  PasteMenuItem->Enabled = true;
13738 // PasteWithAttributesMenuItem->Enabled = true; //new at v2.2.0 - option enabled if cutting
13739  DeleteMenuItem->Enabled = false;
13740  SelectLengthsMenuItem->Enabled = false;
13741  SelectBiDirPrefDirsMenuItem->Visible = false;
13742  CancelSelectionMenuItem->Enabled = false;
13745  if(NeedToLink || TextChangesMade || GraphicChangesMade)
13746  {
13747  ResetChangedFileDataAndCaption(20, true); // true for NonPrefDirChangesMade
13748  }
13749  ClearandRebuildRailway(37); // to overplot the erased elements with SelectBitmap
13750  UserGraphicReselectPanel->Visible = false;
13752  } break;
13753 
13754  case Pasting:
13755  { // have to use braces as otherwise the default case bypasses the initialisation of these local variables
13758  int HDiff = SelectBitmapHLoc - SelectRect.left;
13759  int VDiff = SelectBitmapVLoc - SelectRect.top;
13760  bool NeedToLink = false;
13761  bool TrackLinkingRequiredFlag;
13762  Screen->Cursor = TCursor(-11); // Hourglass;
13763  InfoPanel->Visible = true;
13764  InfoPanel->Caption = "PASTING: Please wait";
13765  InfoPanel->Update();
13766 // erase track elements
13767  int LowSelectHLoc = SelectBitmapHLoc;
13768  int HighSelectHLoc = SelectBitmapHLoc + (SelectBitmap->Width / 16);
13769  int LowSelectVLoc = SelectBitmapVLoc;
13770  int HighSelectVLoc = SelectBitmapVLoc + (SelectBitmap->Height / 16);
13771  bool TrackEraseSuccessfulFlag; // needed but not used here
13772  int ErasedTrackVectorPosition;
13773 // new quick method of erasing, only need H & V values
13774  for(int x = LowSelectHLoc; x < HighSelectHLoc; x++)
13775  {
13776  for(int y = LowSelectVLoc; y < HighSelectVLoc; y++)
13777  {
13778  Track->EraseTrackElement(5, x, y, ErasedTrackVectorPosition, TrackEraseSuccessfulFlag, false);
13779  if(ErasedTrackVectorPosition > -1)
13780  EveryPrefDir->RealignAfterTrackErase(2, ErasedTrackVectorPosition);
13781  }
13782  }
13783 
13784 // erase text elements that fall within region to be overwritten
13785  int LowSelectHPos = SelectBitmapHLoc * 16;
13786  int HighSelectHPos = (SelectBitmapHLoc * 16) + SelectBitmap->Width;
13787  int LowSelectVPos = SelectBitmapVLoc * 16;
13788  int HighSelectVPos = (SelectBitmapVLoc * 16) + SelectBitmap->Height;
13789  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
13790  {
13791  for(TTextHandler::TTextVectorIterator TextPtr = (TextHandler->TextVector.end() - 1); TextPtr >= TextHandler->TextVector.begin();
13792  TextPtr--) // reverse to prevent skipping during erase
13793  {
13794  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
13795  HighSelectVPos))
13796  {
13797  if(TextHandler->TextErase(2, TextPtr->HPos, TextPtr->VPos, AnsiString("")))
13798  {;
13799  } // unused condition
13800  }
13801  }
13802  }
13803 // erase graphic elements that fall wholly within region to be overwritten
13804  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
13805  {
13806  for(TTrack::TUserGraphicVector::iterator GraphicPtr = (Track->UserGraphicVector.end() - 1); GraphicPtr >= Track->UserGraphicVector.begin();
13807  GraphicPtr--) // reverse to prevent skipping during erase
13808  {
13809  if((GraphicPtr->HPos >= LowSelectHPos) && ((GraphicPtr->HPos + GraphicPtr->Width) < HighSelectHPos) && (GraphicPtr->VPos >= LowSelectVPos)
13810  && ((GraphicPtr->VPos + GraphicPtr->Height) < HighSelectVPos))
13811  {
13812  Track->UserGraphicVector.erase(GraphicPtr);
13813  }
13814  }
13815  }
13816  // change the H & V values in SelectVector to the new positions in case Reselect chosen
13817  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
13818  {
13819  Track->SelectVectorAt(35, x).HLoc += HDiff;
13820  Track->SelectVectorAt(1, x).VLoc += VDiff;
13821  }
13822 
13823  // add the new track elements
13824  for(unsigned int x = 0; x < Track->SelectVectorSize(); x++)
13825  {
13826  if(Track->CopyFlag) // blank all names if copying, lengths & speedlimits stay
13827  {
13828  Track->SelectVectorAt(80, x).LocationName = "";
13830  }
13831  bool InternalChecks = false;
13832 // if(Track->PastingWithAttributes) //new at v2.2.0 to select the new funtion & skip multimap checks //drop in v2.4.0
13833 // {
13835  TrackLinkingRequiredFlag, InternalChecks);
13836  // new at v2.2.0 & used in place of PlotAndAddTrackElement to keep length & speed values
13837 // }
13838 /* drop this in v2.4.0 as all pastes are past with attributes
13839  else //'Aspect' parameter added to PlotAndAdd... at v2.2.0 so can plot signals correctly (always four-aspect before)
13840  {
13841  int Aspect;
13842  if(Track->SelectVectorAt(15, x).TrackType != SignalPost) Aspect = 0; //if an '0' value appears with a SignalPost then must be adding track
13843  //this combination allows the funtion to distinguish between adding track and plotting with attributes
13844  else if(Track->SelectVectorAt(16, x).SigAspect == TTrackElement::GroundSignal) Aspect = 1;
13845  else if(Track->SelectVectorAt(17, x).SigAspect == TTrackElement::TwoAspect) Aspect = 2;
13846  else if(Track->SelectVectorAt(18, x).SigAspect == TTrackElement::ThreeAspect) Aspect = 3;
13847  else Aspect = 4;
13848  Track->PlotAndAddTrackElement(2, Track->SelectVectorAt(19, x).SpeedTag, Aspect, Track->SelectVectorAt(20, x).HLoc, Track->SelectVectorAt(21, x).VLoc, TrackLinkingRequiredFlag, InternalChecks);
13849  }
13850 */
13851  if(TrackLinkingRequiredFlag)
13852  NeedToLink = true;
13853  }
13854 
13855  if(!TextHandler->SelectTextVector.empty()) // skip iteration if empty else have an error
13856  {
13857  for(TTextHandler::TTextVectorIterator TextPtr = TextHandler->SelectTextVector.begin(); TextPtr < TextHandler->SelectTextVector.end(); TextPtr++)
13858  {
13859  TextPtr->HPos += HDiff * 16;
13860  TextPtr->VPos += VDiff * 16;
13861  AnsiString TempString = TextPtr->TextString;
13862  // have to create a new TextItem in order to create a new Font object
13863 /* drop in v2.4.0 as all pastes are paste with attributes
13864  if(!Track->PastingWithAttributes) //new at v2.2.0 to deal with the new location prefix '##**' //drop in v2.4.0
13865  {
13866  if(TextPtr->TextString.SubString(1,4) != "##**") //added for named locations so can delete in a simple paste but
13867  //use in PastingWithAttributes
13868  {
13869  TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, TextPtr->TextString, TextPtr->Font);
13870  TextHandler->TextVectorPush(0, TextItem); //if a normal paste include normal text but not location text
13871  }
13872  else TextPtr->TextString = ""; //delete the name for a simple paste
13873  }
13874 */
13875 // else //if pasting with attributes paste all text but strip the '##**' prefix if present
13876 // {
13877  if(TextPtr->TextString.SubString(1, 4) == "##**")
13878  {
13879  TempString = TextPtr->TextString.SubString(5, TextPtr->TextString.Length()); // don't change SelectTextVector value
13880  if(Track->CopyFlag)
13881  {
13882  TextPtr->TextString = ""; // change SelectTextVector value as reselect shouldn't have locations if copied
13883  TempString = "";
13884  }
13885  }
13886  TTextItem TextItem(TextPtr->HPos, TextPtr->VPos, TempString, TextPtr->Font);
13888 // }
13889  }
13890  }
13891  // add new graphic items
13892  if(!Track->SelectGraphicVector.empty()) // skip iteration if empty else have an error
13893  { // keep contents of SelectVector valid in case reselect
13894  for(TTrack::TUserGraphicVector::iterator GraphicPtr = Track->SelectGraphicVector.begin(); GraphicPtr < Track->SelectGraphicVector.end();
13895  GraphicPtr++)
13896  {
13897  GraphicPtr->HPos += HDiff * 16; // for reselect
13898  GraphicPtr->VPos += VDiff * 16; // for reselect
13899  Track->UserGraphicVector.push_back(*GraphicPtr);
13900  }
13901  }
13902  Track->SkipLocationNameMultiMapCheck = false; // renamed in v2.4.0 - reset the flag after pasting complete, otherwise multimap checks always skipped
13903  Track->CopyFlag = false;
13904  Track->CheckMapAndTrack(7); // test
13905  Track->CheckMapAndInactiveTrack(7); // test
13906  Track->CheckLocationNameMultiMap(7); // test
13907  // Track->SetTrackFinished(!NeedToLink); This is an error (see Sam Wainwright email of 24/08/17 & devhistory.txt
13908  // if track not linked to begin with then becomes linked if NeedToLink false
13909  if(NeedToLink)
13910  Track->SetTrackFinished(false); // corrected for v2.1.0
13911  Screen->Cursor = TCursor(-2); // Arrow;
13912  SetTrackBuildImages(14);
13915  SetLevel1Mode(79);
13917  // No further recursion in AddTrack so OK
13918  UserGraphicReselectPanel->Visible = false;
13919  SetLevel2TrackMode(42);
13920  } break;
13921 
13922  case Deleting:
13923  { // have to use braces as otherwise the default case bypasses the initialisation of these local variables
13924  Track->CopyFlag = false;
13925  UnicodeString MessageStr = "Selected area will be deleted - proceed?";
13926  int button = Application->MessageBox(MessageStr.c_str(), L"Please confirm", MB_YESNO);
13927  if(button == IDNO)
13928  {
13929  break;
13930  }
13931  bool EraseSuccessfulFlag, NeedToLink = false, TextChangesMade = false, GraphicChangesMade = false;
13932  int ErasedTrackVectorPosition;
13933  Screen->Cursor = TCursor(-11); // Hourglass;
13934  InfoPanel->Visible = true;
13935  InfoPanel->Caption = "DELETING: Please wait";
13936  InfoPanel->Update();
13937  for(int H = SelectRect.left; H < SelectRect.right; H++)
13938  {
13939  for(int V = SelectRect.top; V < SelectRect.bottom; V++)
13940  {
13941  Track->EraseTrackElement(3, H, V, ErasedTrackVectorPosition, EraseSuccessfulFlag, false);
13942  if(EraseSuccessfulFlag)
13943  {
13944  if(ErasedTrackVectorPosition > -1)
13945  EveryPrefDir->RealignAfterTrackErase(3, ErasedTrackVectorPosition);
13946  NeedToLink = true;
13947  }
13948  }
13949  }
13950  // erase text elements that fall within selected region
13951  int LowSelectHPos = SelectRect.left * 16;
13952  int HighSelectHPos = SelectRect.right * 16;
13953  int LowSelectVPos = SelectRect.top * 16;
13954  int HighSelectVPos = SelectRect.bottom * 16;
13955  if(!TextHandler->TextVector.empty()) // skip iteration if empty else have an error
13956  {
13957  for(TTextHandler::TTextVectorIterator TextPtr = (TextHandler->TextVector.end() - 1); TextPtr >= TextHandler->TextVector.begin();
13958  TextPtr--) // reverse to prevent skipping during erase
13959  {
13960  AnsiString Check = TextPtr->TextString;
13961  if((TextPtr->HPos >= LowSelectHPos) && (TextPtr->HPos < HighSelectHPos) && (TextPtr->VPos >= LowSelectVPos) && (TextPtr->VPos <
13962  HighSelectVPos))
13963  {
13964  if(TextHandler->TextErase(3, TextPtr->HPos, TextPtr->VPos, AnsiString("")))
13965  {;
13966  } // unused condition
13967  TextChangesMade = true;
13968  }
13969  }
13970  }
13971  // erase graphic elements that fall within selected region
13972  if(!Track->UserGraphicVector.empty()) // skip iteration if empty else have an error
13973  {
13974 
13975 //Isglassen05 (vilhelmgg@gmail.com) reported an error via email and attached an error file on 31/07/20. The error was in the following line which was:
13976 
13977 // for(TTrack::TUserGraphicVector::iterator GraphicPtr = (Track->SelectGraphicVector.end() - 1); GraphicPtr >= Track->SelectGraphicVector.begin();
13978 // GraphicPtr--) // reverse to prevent skipping during erase
13979 
13980 //i.e if the railway included one or more user graphics but the SelectGraphicVector didn't include any, then GraphicPtr wouldn't point to anything and the program would fail
13981 //corrected 01/08/20 by using UserGraphicVector (as it should have been) for SelectGraphicVector. New version v2.4.3.
13982 
13983  for(TTrack::TUserGraphicVector::iterator GraphicPtr = (Track->UserGraphicVector.end() - 1); GraphicPtr >= Track->UserGraphicVector.begin();
13984  GraphicPtr--) // reverse to prevent skipping during erase
13985  {
13986  if((GraphicPtr->HPos >= LowSelectHPos) && ((GraphicPtr->HPos + GraphicPtr->Width) < HighSelectHPos) && (GraphicPtr->VPos >= LowSelectVPos)
13987  && ((GraphicPtr->VPos + GraphicPtr->Height) < HighSelectVPos))
13988  {
13989  for(TTrack::TUserGraphicVector::iterator UserGraphicPtr = (Track->UserGraphicVector.end() - 1);
13990  UserGraphicPtr >= Track->UserGraphicVector.begin(); UserGraphicPtr--) // reverse to prevent skipping during erase
13991  {
13992  if((UserGraphicPtr->HPos == GraphicPtr->HPos) && (UserGraphicPtr->VPos == GraphicPtr->VPos) &&
13993  (UserGraphicPtr->Width == GraphicPtr->Width) && (UserGraphicPtr->Height == GraphicPtr->Height) &&
13994  (UserGraphicPtr->FileName == GraphicPtr->FileName))
13995  {
13996  Track->UserGraphicVector.erase(UserGraphicPtr);
13997  GraphicChangesMade = true;
13998  }
13999  }
14000  }
14001  }
14002  }
14003  // clear the selectvectors
14005  TextHandler->SelectTextVector.clear();
14006  Track->SelectGraphicVector.clear();
14007  Track->CheckMapAndTrack(10); // test
14008  Track->CheckMapAndInactiveTrack(9); // test
14009  Track->CheckLocationNameMultiMap(15); // test
14010  // Track->SetTrackFinished(!NeedToLink); This is an error (see Sam Wainwright email of 24/08/17 & devhistory.txt
14011  // if track not linked to begin with then becomes linked if NeedToLink false
14012  if(NeedToLink)
14013  Track->SetTrackFinished(false); // corrected for v2.1.0
14014  if(NeedToLink || TextChangesMade || GraphicChangesMade)
14015  {
14016  ResetChangedFileDataAndCaption(21, true); // true for NonPrefDirChangesMade
14017  }
14018  Screen->Cursor = TCursor(-2); // Arrow;
14021  SetLevel1Mode(80);
14023  // No further recursion in AddTrack so OK
14024  UserGraphicReselectPanel->Visible = false;
14025  SetLevel2TrackMode(43);
14026  } break;
14027 
14028  default:
14029  // No further recursion in TrackMode so OK
14030  Track->CopyFlag = false;
14032  SetLevel1Mode(21);
14033  UserGraphicReselectPanel->Visible = false;
14034  break;
14035  }
14036  Utilities->CallLogPop(107);
14037 }
14038 
14039 // ---------------------------------------------------------------------------
14040 
14042 {
14043  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetLevel2PrefDirMode");
14044  if(Level1Mode != PrefDirMode)
14045  {
14046  // No further recursion in BaseMode so OK
14047  Level1Mode = BaseMode;
14048  SetLevel1Mode(22);
14049  Utilities->CallLogPop(108);
14050  return;
14051  }
14053  {
14054  Utilities->CallLogPop(109);
14055  return;
14056  }
14057 
14058  switch(Level2PrefDirMode) // use the data member
14059  {
14060  case PrefDirContinuing:
14061  { // have to use braces as otherwise the default case bypasses the initialisation of these local variables
14062  InfoPanel->Visible = true;
14063  if(!Display->ZoomOutFlag) // can't set focus if zoomed out, get an error - added this condition for v0.4d
14064  {
14065  AddPrefDirButton->Enabled = true; // this and the line below are to remove focus from any other button that might have it, prior to
14066  AddPrefDirButton->SetFocus(); // disabling the AddPrefDir button, so pressing enter does nothing, it is reset to the AddPrefDir
14067  }
14068  AddPrefDirButton->Enabled = false; // button later if it becomes enabled
14069  DeleteOnePrefDirButton->Enabled = false;
14070  bool LeadingPointsAtLastElement = false;
14071  if(!ConstructPrefDir->EndPossible(0, LeadingPointsAtLastElement))
14072  {
14073  if(LeadingPointsAtLastElement) // size must be > 1
14074  {
14075  InfoPanel->Caption = "PREFERRED DIRECTION SETTING: Can't end on leading points, select next location or truncate";
14076  DeleteOnePrefDirButton->Enabled = true;
14077  }
14078  else // size == 1, DeleteOnePrefDirButton->Enabled remains false
14079  {
14080  InfoPanel->Caption = "PREFERRED DIRECTION SETTING: Select next preferred direction location (right click to truncate)";
14081  }
14082  }
14083  else // size > 1 & EndPossible
14084  {
14085  InfoPanel->Caption = "PREFERRED DIRECTION SETTING: Add selection or select next location (right click to truncate)";
14086  if(!Display->ZoomOutFlag) // can't set focus if zoomed out, get an error - added this condition for v0.4d
14087  {
14088  AddPrefDirButton->Enabled = true;
14089  AddPrefDirButton->SetFocus(); // so can just press 'Enter' key
14090  }
14091  DeleteOnePrefDirButton->Enabled = true;
14092  }
14093  ExitPrefDirButton->Enabled = true;
14094  ClearandRebuildRailway(40); // to show truncated PrefDirs
14095  } break;
14096 
14097  case PrefDirSelecting:
14098  ResetSelectRect(); // so a viewpoint change before a new SelectRect chosen doesn't redisplay the old SelectRect
14099  InfoPanel->Visible = true;
14100  InfoPanel->Caption = "SELECTING: Select area - click left mouse && drag";
14101  SelectMenuItem->Enabled = false;
14102  ReselectMenuItem->Enabled = false;
14103  CancelSelectionMenuItem->Enabled = true;
14104  break;
14105 
14106  default:
14107  // No further recursion in PrefDirMode so OK
14109  SetLevel1Mode(23);
14110  break;
14111  }
14112  Utilities->CallLogPop(110);
14113 }
14114 
14115 // ---------------------------------------------------------------------------
14116 
14118 {
14119  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetLevel2OperMode");
14120  if(Level1Mode != OperMode)
14121  {
14122  // No further recursion in BaseMode so OK
14123  Level1Mode = BaseMode;
14124  SetLevel1Mode(24);
14125  Utilities->CallLogPop(111);
14126  return;
14127  }
14128  if(Level2OperMode == NoOperMode)
14129  {
14130  Utilities->CallLogPop(112);
14131  return;
14132  }
14133  CallingOnButton->Visible = true;
14134  PresetAutoSigRoutesButton->Visible = false;
14135  switch(Level2OperMode) // use the data member
14136  {
14137  case Operating:
14138  { // have to use braces as otherwise the default case bypasses the initialisation of local variables
14139  OperateButton->Enabled = true;
14140  OperateButton->Glyph->LoadFromResourceName(0, "PauseGraphic");
14141  ExitOperationButton->Enabled = true;
14142  TTClockAdjButton->Enabled = false;
14143  if(TTClockSpeed == 2)
14144  TTClockSpeedLabel->Caption = "x2";
14145  else if(TTClockSpeed == 4)
14146  TTClockSpeedLabel->Caption = "x4";
14147  else if(TTClockSpeed == 8)
14148  TTClockSpeedLabel->Caption = "x8";
14149  else if(TTClockSpeed == 16)
14150  TTClockSpeedLabel->Caption = "x16";
14151  else if(TTClockSpeed == 0.5)
14152  TTClockSpeedLabel->Caption = "x1/2";
14153  else if(TTClockSpeed == 0.25)
14154  TTClockSpeedLabel->Caption = "x1/4";
14155  else if(TTClockSpeed == 0.125)
14156  TTClockSpeedLabel->Caption = "x1/8";
14157  else if(TTClockSpeed == 0.0625)
14158  TTClockSpeedLabel->Caption = "x1/16";
14159  else
14160  {
14161  TTClockSpeed = 1;
14162  TTClockSpeedLabel->Caption = "x1";
14163  }
14164  AnsiString TimeMessage = Utilities->Format96HHMMSS(TDateTime(PauseEntryRestartTime)) + ": ";
14166  {
14167  // send message to performance log
14168  if(TTClockSpeed == 2)
14169  Display->PerformanceLog(6, TimeMessage + "Timetable clock speed changed to twice normal");
14170  else if(TTClockSpeed == 4)
14171  Display->PerformanceLog(7, TimeMessage + "Timetable clock speed changed to four times normal");
14172  else if(TTClockSpeed == 8)
14173  Display->PerformanceLog(8, TimeMessage + "Timetable clock speed changed to eight times normal");
14174  else if(TTClockSpeed == 16)
14175  Display->PerformanceLog(9, TimeMessage + "Timetable clock speed changed to sixteen times normal");
14176  else if(TTClockSpeed == 0.5)
14177  Display->PerformanceLog(10, TimeMessage + "Timetable clock speed changed to half normal");
14178  else if(TTClockSpeed == 0.25)
14179  Display->PerformanceLog(11, TimeMessage + "Timetable clock speed changed to quarter normal");
14180  else if(TTClockSpeed == 0.125)
14181  Display->PerformanceLog(14, TimeMessage + "Timetable clock speed changed to one eighth normal");
14182  else if(TTClockSpeed == 0.0625)
14183  Display->PerformanceLog(15, TimeMessage + "Timetable clock speed changed to one sixteenth normal");
14184  else
14185  Display->PerformanceLog(12, TimeMessage + "Timetable clock speed changed to normal");
14186  }
14187  double TTClockTimeChange = double(TrainController->RestartTime) - PauseEntryRestartTime;
14188  if(TTClockTimeChange > 0.000347) // 30 seconds, min increase is 1 minute & don't trust doubles to stay exactly equal
14189  {
14190  // send message to performance log
14191  int MinsIncrease = ((TTClockTimeChange * 1440) + 0.5); // add 30 secs to ensure truncates correctly
14192  int HoursIncrease = 0;
14193  while(MinsIncrease >= 60)
14194  {
14195  HoursIncrease++;
14196  MinsIncrease -= 60;
14197  }
14198  if(HoursIncrease == 0)
14199  TimeMessage += "Timetable clock incremented by " + AnsiString(MinsIncrease) + "m";
14200  else if(MinsIncrease == 0)
14201  TimeMessage += "Timetable clock incremented by " + AnsiString(HoursIncrease) + "h";
14202  else
14203  TimeMessage += "Timetable clock incremented by " + AnsiString(HoursIncrease) + "h " + AnsiString(MinsIncrease) + "m";
14204  Display->PerformanceLog(13, TimeMessage);
14205  }
14206  WarningHover = false;
14209  {
14210  MTBFEditBox->Visible = true;
14211  MTBFEditBox->Text = AnsiString(TrainController->AvHoursIntValue);
14212  MTBFEditBox->ReadOnly = true; // because this is not prestart mode
14213  MTBFLabel->Visible = true;
14214  MTBFLabel->Caption = "Mean time between\ntrain failures in\ntimetable hours";
14216  }
14217  else
14218  {
14219  MTBFEditBox->Visible = false;
14220  MTBFEditBox->Text = "";
14221  MTBFLabel->Visible = false;
14222  MTBFLabel->Caption = "Mean time between\ntrain failures in\ntimetable hours";
14224  }
14225  TrainController->BaseTime = TDateTime::CurrentDateTime();
14226 // StopTTClockFlag already false because TTClock stopped by condition "if(!TrainController->StopTTClockFlag && (Level2OperMode == Operating))" in MasterClockTimer function
14227  } break;
14228 
14229  case Paused:
14230  OperateButton->Enabled = true;
14231  OperateButton->Glyph->LoadFromResourceName(0, "RunGraphic");
14232  ExitOperationButton->Enabled = true;
14233  TTClockAdjButton->Enabled = true;
14238 // StopTTClockFlag stays false because TTClock stopped by condition "if(!TrainController->StopTTClockFlag && (Level2OperMode == Operating))" in MasterClockTimer function
14241  break;
14242 
14243  // don't need a separate case for PreStart
14244 
14245  default:
14246  // No further recursion in OperMode so OK
14247  Level1Mode = OperMode;
14248  SetLevel1Mode(25);
14249  break;
14250  }
14251  Utilities->CallLogPop(113);
14252 }
14253 
14254 // ---------------------------------------------------------------------------
14255 
14256 void TInterface::ApproachLocking(int Caller, TDateTime TTClockTime)
14257 {
14258  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ApproachLocking");
14259  float LockDelay = 120.0;
14260 
14261  if(!AllRoutes->LockedRouteVector.empty())
14262  {
14263  for(TAllRoutes::TLockedRouteVectorIterator LRVIT = AllRoutes->LockedRouteVector.end() - 1; LRVIT >= AllRoutes->LockedRouteVector.begin(); LRVIT--)
14264  {
14265  bool BreakFlag = false;
14266  if(AllRoutes->TrackIsInARoute(5, LRVIT->LastTrackVectorPosition, LRVIT->LastXLinkPos))
14267  {
14268  TOneRoute &Route = AllRoutes->GetModifiableRouteAt(0, LRVIT->RouteNumber);
14269  if((TTClockTime - LRVIT->LockStartTime) > TDateTime(LockDelay / 86400))
14270  {
14271  TrainController->LogEvent("LockedRouteRemoved," + AnsiString(LRVIT->TruncateTrackVectorPosition) + "," +
14272  AnsiString(LRVIT->LastTrackVectorPosition));
14273  while(Route.LastElementPtr(9)->GetTrackVectorPosition() != LRVIT->TruncateTrackVectorPosition)
14274  { // examine the element one earlier in the route than the last
14275  if(!(AllRoutes->TrackIsInARoute(6, Route.LastElementPtr(10)->Conn[Route.LastElementPtr(11)->GetELinkPos()],
14276  Route.LastElementPtr(12)->ConnLinkPos[Route.LastElementPtr(13)->GetELinkPos()])))
14277  {
14278  BreakFlag = true;
14279  }
14280  AllRoutes->RemoveRouteElement(1, Route.LastElementPtr(14)->HLoc, Route.LastElementPtr(15)->VLoc, Route.LastElementPtr(16)->GetELink());
14281  if(BreakFlag)
14282  break; // train removed earlier element from route so stop here
14283  }
14284  if(!BreakFlag)
14285  { // still need to remove the element at the TruncateTrackVectorPosition
14286  if(Route.LastElementPtr(17)->GetTrackVectorPosition() == LRVIT->TruncateTrackVectorPosition)
14287  {
14288  AllRoutes->RemoveRouteElement(2, Route.LastElementPtr(18)->HLoc, Route.LastElementPtr(19)->VLoc,
14289  Route.LastElementPtr(20)->GetELink());
14290  }
14291  }
14292  AllRoutes->CheckMapAndRoutes(10); // test
14293  AllRoutes->LockedRouteVector.erase(LRVIT);
14294  if(!Display->ZoomOutFlag)
14295  ClearandRebuildRailway(17); // to get rid of route graphics
14297  }
14298  }
14299  else
14300  {
14301  AllRoutes->LockedRouteVector.erase(LRVIT);
14302  // if end element not in route then a train must have entered it from the wrong end and erased the whole route,
14303  // hence no longer needed so get rid of it
14304  }
14305  }
14306  }
14307  Utilities->CallLogPop(743);
14308 }
14309 
14310 // ---------------------------------------------------------------------------
14311 
14312 void TInterface::ContinuationAutoSignals(int Caller, TDateTime TTClockTime)
14313 {
14314  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ContinuationAutoSignals");
14316  {
14318  for(AutoSigVectorIT = TrainController->ContinuationAutoSigVector.end() - 1; AutoSigVectorIT >= TrainController->ContinuationAutoSigVector.begin();
14319  AutoSigVectorIT--)
14320  {
14321  // Below added at v2.1.0 to prevent locked autosig continuation routes from clearing signals
14322  // need to identify the Continuation element in the route & check if it's in a locked route. If it is then don't call
14323  // SetTrailingSignalsOnContinuationRoute as all signals must stay red.
14324  TPrefDirElement TempPrefDirElement;
14325  int TempLockedVectorNumber;
14326  int LastRouteElement = AllRoutes->GetFixedRouteAt(220, AutoSigVectorIT->RouteNumber).PrefDirSize() - 1;
14327  int TVNum = AllRoutes->GetFixedRouteAt(221, AutoSigVectorIT->RouteNumber).GetFixedPrefDirElementAt(246, LastRouteElement).GetTrackVectorPosition();
14328  // this will be a continuation (error thrown in SetTrailingSignalsOnContinuationRoute if not) & XLinkPos is always 0 for
14329  // route exiting at a continuation
14330  if(AllRoutes->IsElementInLockedRouteGetPrefDirElementGetLockedVectorNumber(14, TVNum, 0, TempPrefDirElement, TempLockedVectorNumber))
14331  {
14332  continue;
14333  }
14334  // end of additions
14335  if(((TTClockTime - AutoSigVectorIT->PassoutTime) > TDateTime(AutoSigVectorIT->FirstDelay / 86400)) && (AutoSigVectorIT->AccessNumber == 0))
14336  {
14337  AllRoutes->SetTrailingSignalsOnContinuationRoute(1, AutoSigVectorIT->RouteNumber, 0);
14338  AutoSigVectorIT->AccessNumber++;
14339  continue;
14340  }
14341  if(((TTClockTime - AutoSigVectorIT->PassoutTime) > TDateTime(AutoSigVectorIT->SecondDelay / 86400)) && (AutoSigVectorIT->AccessNumber == 1))
14342  {
14343  AllRoutes->SetTrailingSignalsOnContinuationRoute(2, AutoSigVectorIT->RouteNumber, 1);
14344  AutoSigVectorIT->AccessNumber++;
14345  continue;
14346  }
14347  if(((TTClockTime - AutoSigVectorIT->PassoutTime) > TDateTime(AutoSigVectorIT->ThirdDelay / 86400)) && (AutoSigVectorIT->AccessNumber == 2))
14348  {
14349  AllRoutes->SetTrailingSignalsOnContinuationRoute(3, AutoSigVectorIT->RouteNumber, 2);
14350  AutoSigVectorIT->AccessNumber++;
14351  continue;
14352  }
14353  }
14354  // examine all vector for any expired values & erase
14355  for(AutoSigVectorIT = TrainController->ContinuationAutoSigVector.end() - 1; AutoSigVectorIT >= TrainController->ContinuationAutoSigVector.begin();
14356  AutoSigVectorIT--)
14357  {
14358  if(AutoSigVectorIT->AccessNumber > 2)
14359  {
14360  TrainController->ContinuationAutoSigVector.erase(AutoSigVectorIT); // erase expired entries - reverse interation so OK to erase
14361  }
14362  }
14363  }
14364  Utilities->CallLogPop(744);
14365 }
14366 
14367 // ---------------------------------------------------------------------------
14368 
14370 {
14371  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",TrackTrainFloat");
14372 
14373  TPoint MousePoint = Mouse->CursorPos;
14374  int ScreenX = MousePoint.x - MainScreen->ClientOrigin.x;
14375  int ScreenY = MousePoint.y - MainScreen->ClientOrigin.y;
14376 
14377  if((ScreenX > (MainScreen->Width - 1)) || (ScreenY > (MainScreen->Height - 1)) || (ScreenX < 0) || (ScreenY < 0))
14378  {
14379  FloatingPanel->Visible = false;
14380  Utilities->CallLogPop(1432);
14381  return;
14382  }
14383 
14384  if(PerformancePanel->Visible)
14385  {
14386  if((MousePoint.x >= PerformancePanel->Left) && (MousePoint.x <= (PerformancePanel->Left + PerformancePanel->Width)) &&
14387  ((MousePoint.y - ClientOrigin.y) >= PerformancePanel->Top) && ((MousePoint.y - ClientOrigin.y) <=
14388  (PerformancePanel->Top + PerformancePanel->Height)))
14389  { // dont show floating window if mouse over performance panel
14390  FloatingPanel->Visible = false;
14391  Utilities->CallLogPop(1715);
14392  return;
14393  }
14394  }
14395 
14396  if(OperatorActionPanel->Visible) // added at v2.3.0 as showed info from behind panel - thanks to Xeon who notified me in email of 15/10/19
14397  {
14398  if((MousePoint.x >= OperatorActionPanel->Left) && (MousePoint.x <= (OperatorActionPanel->Left + OperatorActionPanel->Width)) &&
14399  ((MousePoint.y - ClientOrigin.y) >= OperatorActionPanel->Top) && ((MousePoint.y - ClientOrigin.y) <=
14400  (OperatorActionPanel->Top + OperatorActionPanel->Height)))
14401  { // dont show floating window if mouse over OperatorActionPanel
14402  FloatingPanel->Visible = false;
14403  Utilities->CallLogPop(2098);
14404  return;
14405  }
14406  }
14407 
14408  if(TimetableEditPanel->Visible) // added at v2.5.1 as showed track info behind panel
14409  {
14410  if((MousePoint.x >= TimetableEditPanel->Left) && (MousePoint.x <= (TimetableEditPanel->Left + TimetableEditPanel->Width)) &&
14411  ((MousePoint.y - ClientOrigin.y) >= TimetableEditPanel->Top) && ((MousePoint.y - ClientOrigin.y) <=
14412  (TimetableEditPanel->Top + TimetableEditPanel->Height)))
14413  { // dont show floating window if mouse over TimetableEditPanel
14414  FloatingPanel->Visible = false;
14415  Utilities->CallLogPop(2240);
14416  return;
14417  }
14418  }
14419 
14420  AnsiString TrackFloat = "", TrainStatusFloat = "", TrainTTFloat = "";
14421 
14422  bool ShowTrackFloatFlag = false, ShowTrainStatusFloatFlag = false, ShowTrainTTFloatFlag = false;
14423  int HLoc, VLoc;
14424 
14425  Track->GetTrackLocsFromScreenPos(4, HLoc, VLoc, ScreenX, ScreenY);
14426 
14427  if(Display->ZoomOutFlag)
14428  {
14429  Utilities->CallLogPop(1123);
14430  return;
14431  }
14432  if(TrackInfoOnOffMenuItem->Caption == "Hide")
14433  {
14434  bool ActiveTrackFoundFlag = false, InactiveTrackFoundFlag = false, TwoTrack = false;
14435  AnsiString Length01Str = "", Length23Str = "", SpeedLimit01Str = "", SpeedLimit23Str = "";
14436  AnsiString StationEntryStopLinkPos1Str = "", StationEntryStopLinkPos2Str = "";
14437  AnsiString ATrackSN = "", ATrackTN = "", IATrackSN = "", LengthAndSpeedCaption = "";
14438  AnsiString SigAspectString = ""; // new at version 0.6
14439  int ActiveVecPos = Track->GetVectorPositionFromTrackMap(5, HLoc, VLoc, ActiveTrackFoundFlag);
14440  TTrack::TIMPair InactiveVecPositions = Track->GetVectorPositionsFromInactiveTrackMap(3, HLoc, VLoc, InactiveTrackFoundFlag);
14441  TTrackElement ActiveTrackElement, InactiveTrackElement;
14442  if(InactiveTrackFoundFlag)
14443  {
14444  InactiveTrackElement = Track->InactiveTrackElementAt(32, InactiveVecPositions.first); // only need one for the name
14445  IATrackSN = InactiveTrackElement.LocationName;
14446  }
14447  if(ActiveTrackFoundFlag)
14448  {
14449  ActiveTrackElement = Track->TrackElementAt(449, ActiveVecPos);
14450  ATrackSN = ActiveTrackElement.LocationName;
14451  StationEntryStopLinkPos1Str = AnsiString(ActiveTrackElement.StationEntryStopLinkPos1);
14452  StationEntryStopLinkPos2Str = AnsiString(ActiveTrackElement.StationEntryStopLinkPos2);
14453  ATrackTN = ActiveTrackElement.ActiveTrackElementName;
14454  if((ATrackTN != "") && (!InactiveTrackFoundFlag || ((InactiveTrackElement.TrackType != Platform) &&
14455  (InactiveTrackElement.TrackType != NamedNonStationLocation)) ||
14456  (InactiveTrackElement.LocationName != ActiveTrackElement.ActiveTrackElementName)))
14457  {
14458  ShowMessage("Error - Track has timetable name without corresponding plat/named loc");
14459  }
14460  if(InactiveTrackFoundFlag && ((InactiveTrackElement.TrackType == Platform) || (InactiveTrackElement.TrackType == NamedNonStationLocation)) &&
14461  (InactiveTrackElement.LocationName != ActiveTrackElement.ActiveTrackElementName))
14462  {
14463  ShowMessage("Error - plat/named loc and track have different names, or plat/named loc named but not track");
14464  }
14465  if((ActiveTrackElement.TrackType == Points) || (ActiveTrackElement.TrackType == Bridge) || (ActiveTrackElement.TrackType == Crossover))
14466  {
14467  TwoTrack = true;
14468  }
14469  Length01Str = AnsiString(ActiveTrackElement.Length01);
14470  if(Length01Str == "-1")
14471  Length01Str = "Not Set";
14472  SpeedLimit01Str = AnsiString(ActiveTrackElement.SpeedLimit01);
14473  if(SpeedLimit01Str == "-1")
14474  SpeedLimit01Str = "Not Set";
14475  if(TwoTrack)
14476  {
14477  Length23Str = AnsiString(ActiveTrackElement.Length23);
14478  if(Length23Str == "-1")
14479  Length23Str = "Not Set"; // shouldn't be -1 but leave in
14480  SpeedLimit23Str = AnsiString(ActiveTrackElement.SpeedLimit23);
14481  if(SpeedLimit23Str == "-1")
14482  SpeedLimit23Str = "Not Set"; // shouldn't be -1 but leave in
14483  if((ActiveTrackElement.TrackType == Points) && (ActiveTrackElement.SpeedTag < 132))
14484  {
14485  LengthAndSpeedCaption = "Straight track length = " + Length01Str + " m" + '\n' + "Diverging track length = " + Length23Str + " m" + '\n' +
14486  "Straight track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Diverging track speed limit = " + SpeedLimit23Str + " km/h";
14487  }
14488  else if(ActiveTrackElement.TrackType == Points)
14489  {
14490  LengthAndSpeedCaption = "Left diverging track length = " + Length01Str + " m" + '\n' + "Right diverging track length = " + Length23Str +
14491  " m" + '\n' + "Left diverging track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Right diverging track Speed Limit = " +
14492  SpeedLimit23Str + " km/h";
14493  }
14494  else if(ActiveTrackElement.TrackType == Crossover)
14495  // crossover links 0 & 1 = diagonal top left to Bottom right, then horizontal, then vertical
14496  {
14497  if((ActiveTrackElement.SpeedTag == 15) || (ActiveTrackElement.SpeedTag == 46))
14498  {
14499  LengthAndSpeedCaption = "Horizontal track length = " + Length01Str + " m" + '\n' + "Other track length = " + Length23Str + " m" + '\n' +
14500  "Horizontal track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Other track speed limit = " + SpeedLimit23Str + " km/h";
14501  }
14502  else if(ActiveTrackElement.SpeedTag == 47)
14503  {
14504  LengthAndSpeedCaption = "Horizontal track length = " + Length23Str + " m" + '\n' + "Other track length = " + Length01Str + " m" + '\n' +
14505  "Horizontal track speed limit = " + SpeedLimit23Str + " km/h" + '\n' + "Other track speed limit = " + SpeedLimit01Str + " km/h";
14506  }
14507  else if(ActiveTrackElement.SpeedTag == 45)
14508  {
14509  LengthAndSpeedCaption = "Vertical track length = " + Length01Str + " m" + '\n' + "Other track length = " + Length23Str + " m" + '\n' +
14510  "Vertical track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Other track speed limit = " + SpeedLimit23Str + " km/h";
14511  }
14512  else if(ActiveTrackElement.SpeedTag == 44)
14513  {
14514  LengthAndSpeedCaption = "Vertical track length = " + Length23Str + " m" + '\n' + "Other track length = " + Length01Str + " m" + '\n' +
14515  "Vertical track speed limit = " + SpeedLimit23Str + " km/h" + '\n' + "Other track speed limit = " + SpeedLimit01Str + " km/h";
14516  }
14517  else if(ActiveTrackElement.SpeedTag == 16)
14518  {
14519  LengthAndSpeedCaption = "Top left to bottom right track length = " + Length01Str + " m" + '\n' + "Other track length = " + Length23Str +
14520  " m" + '\n' + "Top left to bottom right track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Other track speed limit = " +
14521  SpeedLimit23Str + " km/h";
14522  }
14523  }
14524  else // bridge
14525  {
14526  LengthAndSpeedCaption = "Top track length = " + Length01Str + " m" + '\n' + "Bottom track length = " + Length23Str + " m" + '\n' +
14527  "Top track speed limit = " + SpeedLimit01Str + " km/h" + '\n' + "Bottom track speed limit = " + SpeedLimit23Str + " km/h";
14528  }
14529  }
14530  else
14531  {
14532  LengthAndSpeedCaption = "Track length = " + Length01Str + " m" + '\n' + "Track speed limit = " + SpeedLimit01Str + " km/h";
14533  }
14534  }
14535  if(ActiveTrackFoundFlag)
14536  {
14537  // note that now the "In timetable..." line removed much of the below could be simplified, but leave as is
14538  // in case wish to resurrect this line for any reason
14539  ShowTrackFloatFlag = true;
14540  if(ATrackTN != "") // has a timetable name & therefore has a valid platform or non-station name
14541  {
14542  TrackFloat = "Location = " + ATrackTN + '\n' + LengthAndSpeedCaption + '\n' + "ID = " + AnsiString(ActiveTrackElement.ElementID);
14543  }
14544  else if(ATrackSN != "") // no timetable name but location name, i.e. a footcrossing
14545  {
14546  TrackFloat = "Location = " + ATrackSN + '\n' + LengthAndSpeedCaption + '\n' + "ID = " + AnsiString(ActiveTrackElement.ElementID);
14547  }
14548 
14549  else if(InactiveTrackFoundFlag) // no timetable name yet but unnamed inactive element at same location (can't be a parapet if active element there)
14550  {
14551  TrackFloat = "Location unnamed\n" + LengthAndSpeedCaption + '\n' + "ID = " + AnsiString(ActiveTrackElement.ElementID);
14552  }
14553 
14554  else // no timetable or location name, just track
14555  {
14556  TrackFloat = LengthAndSpeedCaption + '\n' + "Track Element ID = " + AnsiString(ActiveTrackElement.ElementID);
14557  }
14558  if(ActiveTrackElement.TrackType == SignalPost) // new for version 0.6
14559  {
14560  if(ActiveTrackElement.SigAspect == TTrackElement::ThreeAspect)
14561  {
14562  SigAspectString = "\nThree-aspect signal";
14563  }
14564  else if(ActiveTrackElement.SigAspect == TTrackElement::TwoAspect)
14565  {
14566  SigAspectString = "\nTwo-aspect signal";
14567  }
14568  else if(ActiveTrackElement.SigAspect == TTrackElement::GroundSignal)
14569  {
14570  SigAspectString = "\nGround signal";
14571  }
14572  else
14573  {
14574  SigAspectString = "\nFour-aspect signal";
14575  }
14576  TrackFloat += SigAspectString;
14577  }
14578  } // if(ActiveFoundFlag)
14579  else if(InactiveTrackFoundFlag) // inactive element but no active element,
14580  // i.e. concourse or non-station name at a blank element
14581  {
14582  ShowTrackFloatFlag = true;
14583  if(InactiveTrackElement.TrackType != Parapet)
14584  {
14585  if(IATrackSN == "")
14586  {
14587  TrackFloat = "Location unnamed\nID = " + AnsiString(InactiveTrackElement.ElementID);
14588  }
14589  else
14590  {
14591  TrackFloat = "Location = " + IATrackSN + '\n' + "ID = " + AnsiString(InactiveTrackElement.ElementID);
14592  }
14593  }
14594  else // it is a parapet, just show the ID
14595  {
14596  TrackFloat = "ID = " + AnsiString(InactiveTrackElement.ElementID);
14597  }
14598  }
14599  }
14600 // end of TrackFloat section
14601 
14602  if(Level1Mode == OperMode && ((TrainStatusInfoOnOffMenuItem->Caption == "Hide Status") || (TrainTTInfoOnOffMenuItem->Caption == "Hide Timetable")))
14603  // if caption is 'Hide' label is required
14604  {
14605  bool FoundFlag;
14606  AnsiString FormatOneDPStr = "####0.0";
14607  AnsiString FormatNoDPStr = "#######0";
14608 // AnsiString Format5DPStr = "####0.00000"; //temporary
14609  AnsiString MaxBrakeStr = ""; // , EntrySpeedStr="", HalfStr="", FullStr="", MaxAtHalfStr="";//test
14610  AnsiString SpecialStr = "", MaxSpeedStr = "";
14611  int VecPos = Track->GetVectorPositionFromTrackMap(6, HLoc, VLoc, FoundFlag);
14612  if(FoundFlag)
14613  {
14614  if(Track->TrackElementAt(450, VecPos).TrainIDOnElement > -1)
14615  // if a bridge & 2 trains at that position will select the train with TrainIDOnElement set
14616  {
14618  if(TrainStatusInfoOnOffMenuItem->Caption == "Hide Status")
14619  {
14620  ShowTrainStatusFloatFlag = true;
14621  AnsiString HeadCode = "", ServiceReferenceInfo = "", Status = "", CurrSpeedStr = "", BrakePCStr = "", NextStopStr = "", TimeLeftStr = "",
14622  TimeToNextMovementStr = "", MassStr = "", PowerStr = "";
14623  double CurrSpeed;
14624  MassStr = AnsiString::FormatFloat(FormatNoDPStr, ((double)Train.Mass) / 1000); // Te
14625  PowerStr = AnsiString::FormatFloat(FormatNoDPStr, Train.PowerAtRail / 1000 / 0.8); // kW
14626  if(Train.BeingCalledOn)
14627  MaxSpeedStr = "30";
14628  else
14629  MaxSpeedStr = AnsiString::FormatFloat(FormatNoDPStr, Train.MaxRunningSpeed);
14630  TDateTime ElapsedDeltaT = TrainController->TTClockTime - Train.EntryTime;
14631  TDateTime FirstHalfTimeDeltaT = Train.ExitTimeHalf - Train.EntryTime;
14632  TDateTime SecondHalfTimeDeltaT = Train.ExitTimeFull - Train.EntryTime - FirstHalfTimeDeltaT;
14633  TDateTime TimeLeft;
14634  double BrakePCRate = Train.BrakeRate * 100.0 / Train.MaxBrakeRate;
14635  MaxBrakeStr = AnsiString::FormatFloat(FormatNoDPStr, (Train.MaxBrakeRate * Train.Mass / 9810));
14636  HeadCode = Train.HeadCode;
14637  if(Train.TrainDataEntryPtr->NumberOfTrains > 1) // Service reference information added at v0.6b
14638  {
14639  if(Train.RepeatNumber == 0)
14640  {
14641  if(HeadCode != Train.TrainDataEntryPtr->ServiceReference)
14642  ServiceReferenceInfo = "\nFirst service of ref. " + Train.TrainDataEntryPtr->ServiceReference;
14643  else
14644  ServiceReferenceInfo = "\nFirst service";
14645  }
14646  else if(HeadCode == Train.TrainDataEntryPtr->ServiceReference)
14647  ServiceReferenceInfo = "\nRepeat service no. " + AnsiString(Train.RepeatNumber);
14648  else
14649  ServiceReferenceInfo = "\nRepeat service no. " + AnsiString(Train.RepeatNumber) + " of ref. " +
14651  }
14652  else
14653  {
14654  if(HeadCode != Train.TrainDataEntryPtr->ServiceReference)
14655  ServiceReferenceInfo = "\nService reference " + Train.TrainDataEntryPtr->ServiceReference;
14656  }
14657  if(Train.Stopped())
14658  {
14659  if(Train.SignallerStopped)
14660  Status = "Stopped on signaller's instruction"; // if stopped for any other reason that will diplay
14661  if(Train.NotInService)
14662  Status = "Not in service"; // not used so far but leave it in
14663  if(Train.StoppedAtBuffers)
14664  Status = "Stopped at buffers";
14665  if(Train.StoppedAtSignal)
14666  Status = "Stopped at signal";
14667  if(Train.StoppedForTrainInFront)
14668  Status = "Stopped - forward track occupied"; // before station stop as want to display station stop if that set
14669  if(Train.StoppedAtLocation)
14670  Status = "Stopped at " + Train.ActionVectorEntryPtr->LocationName;
14671  if((Train.StoppedAtLocation) && (Train.StoppedForTrainInFront))
14672  Status = "Stopped at " + Train.ActionVectorEntryPtr->LocationName + " + forward track occupied";
14673  if(Train.StoppedWithoutPower)
14674  {
14675  if(Train.TrainFailed)
14676  Status = "Stopped without power - train failed";
14677  else
14678  Status = "Stopped without power";
14679  }
14680  if(Train.StoppedAfterSPAD)
14681  Status = "Stopped - signal passed at danger";
14682  if(Train.Derailed)
14683  Status = "Derailed";
14684  if(Train.Crashed)
14685  Status = "Crashed";
14686  CurrSpeed = 0;
14687  }
14688  else if(Train.OneLengthAccelDecel)
14689  {
14690  if(Train.FirstHalfMove)
14691  {
14692  Status = "Accelerating"; // just display a linear speed rise over half length
14693  BrakePCRate = 0; // reset to proper value during braking
14694  CurrSpeed = Train.EntrySpeed + ((Train.ExitSpeedHalf - Train.EntrySpeed) * (double(ElapsedDeltaT) / double(FirstHalfTimeDeltaT)));
14695  }
14696  else
14697  {
14698  BrakePCRate = Train.BrakeRate * 100.0 / Train.MaxBrakeRate;
14699  if(BrakePCRate < 55)
14700  Status = "Light braking";
14701  else if(BrakePCRate < 90)
14702  Status = "Heavy braking";
14703  else
14704  Status = "Emergency braking";
14705  CurrSpeed = Train.ExitSpeedHalf - 3.6 * (Train.BrakeRate * (TrainController->TTClockTime - Train.ExitTimeHalf) * 86400.0);
14706  }
14707  }
14708  else if(Train.BrakeRate > 0.01)
14709  {
14710  if(BrakePCRate < 55)
14711  Status = "Light braking";
14712  else if(BrakePCRate < 90)
14713  Status = "Heavy braking";
14714  else
14715  Status = "Emergency braking";
14716  CurrSpeed = Train.EntrySpeed - 3.6 * (Train.BrakeRate * ElapsedDeltaT * 86400.0);
14717  }
14718 
14719  else if((Train.BrakeRate <= 0.01) && (Train.ExitSpeedHalf > (Train.EntrySpeed + 0.01)) && Train.FirstHalfMove)
14720  {
14721  Status = "Accelerating"; // just display a linear speed rise over half length
14722  CurrSpeed = Train.EntrySpeed + ((Train.ExitSpeedHalf - Train.EntrySpeed) * (double(ElapsedDeltaT) / double(FirstHalfTimeDeltaT)));
14723  }
14724 
14725  else if((Train.BrakeRate <= 0.01) && (Train.ExitSpeedFull > (Train.ExitSpeedHalf + 0.01)) && !Train.FirstHalfMove)
14726  {
14727  Status = "Accelerating";
14728  CurrSpeed = Train.ExitSpeedHalf +
14729  ((Train.ExitSpeedFull - Train.ExitSpeedHalf) * (double(ElapsedDeltaT - FirstHalfTimeDeltaT) / double(SecondHalfTimeDeltaT)));
14730  }
14731 
14732  else if((Train.BrakeRate <= 0.01) && (Train.ExitSpeedFull <= Train.ExitSpeedHalf) && !Train.FirstHalfMove)
14733  {
14734  if(Train.PowerAtRail < 1)
14735  {
14736  if(Train.TrainFailed)
14737  {
14738  Status = "Coasting - train failed";
14739  }
14740  else
14741  {
14742  Status = "Coasting - no power";
14743  }
14744  CurrSpeed = Train.ExitSpeedFull;
14745  }
14746  else
14747  {
14748  Status = "Constant speed";
14749  CurrSpeed = Train.ExitSpeedFull;
14750  }
14751  }
14752 
14753  else // No braking, first half move, ExitSpeedHalf <= EntrySpeed
14754  {
14755  if(Train.PowerAtRail < 1) // as designed there is no way a vehicle can coast without having failed
14756  {
14757  if(Train.TrainFailed)
14758  {
14759  Status = "Coasting - train failed";
14760  }
14761  else
14762  {
14763  Status = "Coasting - no power";
14764  }
14765  CurrSpeed = Train.ExitSpeedHalf;
14766  }
14767  else
14768  {
14769  Status = "Constant speed";
14770  CurrSpeed = Train.ExitSpeedHalf;
14771  }
14772  }
14773  if(Train.TimetableFinished)
14774  {
14775  if(Train.TrainMode == Signaller)
14776  NextStopStr = "At signaller's discretion";
14777  else
14778  NextStopStr = "None";
14779  }
14780  else
14781  NextStopStr = Train.FloatingLabelNextString(0, Train.ActionVectorEntryPtr);
14782  if(Train.TrainMode == Signaller)
14783  {
14784  SpecialStr = "Train under signaller control" + AnsiString('\n');
14785  }
14786  else if(Train.BeingCalledOn && !Train.StoppedAtLocation)
14787  {
14788  SpecialStr = "Restricted speed - being called on" + AnsiString('\n');
14789  }
14790 
14791  double RemTimeHalf = 86400.0 * double(Train.ExitTimeHalf - TrainController->TTClockTime);
14792  if(RemTimeHalf < 0)
14793  RemTimeHalf = 0;
14794  double RemTimeFull = 86400.0 * double(Train.ExitTimeFull - TrainController->TTClockTime);
14795  if(RemTimeFull < 0)
14796  RemTimeFull = 0;
14797  if(RemTimeHalf > 0)
14798  TimeLeft = RemTimeHalf;
14799  else
14800  TimeLeft = RemTimeFull;
14801  TimeToNextMovementStr = "Time to next movement (sec) = " + TimeLeftStr.FormatFloat(FormatOneDPStr, TimeLeft);
14802  if(Train.Stopped())
14803  TimeToNextMovementStr = "";
14804  if(Train.Stopped())
14805  {
14806  TrainStatusFloat = HeadCode + ": " + Train.TrainDataEntryPtr->Description + ServiceReferenceInfo + '\n' + "Maximum train speed " +
14807  MaxSpeedStr + "km/h; Power " + PowerStr + "kW" + '\n' + "Mass " + MassStr + "Te; Brakes " + MaxBrakeStr + "Te" + '\n' + SpecialStr +
14808  Status + '\n' + "Next: " + NextStopStr;
14809  }
14810  else
14811  {
14812  TrainStatusFloat = HeadCode + ": " + Train.TrainDataEntryPtr->Description + ServiceReferenceInfo + '\n' + "Maximum train speed " +
14813  MaxSpeedStr + "km/h; Power " + PowerStr + "kW" + '\n' + "Mass " + MassStr + "Te; Brakes " + MaxBrakeStr + "Te" + '\n' + SpecialStr +
14814  Status + ": " + CurrSpeedStr.FormatFloat(FormatNoDPStr, CurrSpeed) + "km/h" + '\n' + "Next: " + NextStopStr;
14815  }
14816  }
14817  if(TrainTTInfoOnOffMenuItem->Caption == "Hide Timetable")
14818  {
14819  ShowTrainTTFloatFlag = true;
14820  TrainTTFloat = Train.FloatingTimetableString(0, Train.ActionVectorEntryPtr);
14821  }
14822  }
14823 
14824  else if(Track->TrackElementAt(666, VecPos).TrackType == Continuation)
14825  // always give train information if a train present, but if not & either of train status or timetable info
14826  // selected then give next expected train to enter, or 'No trains expected'
14827  {
14828  TrainStatusFloat = "No trains expected";
14829  TrainTTFloat = "No timetable";
14830  float EntrySpeed;
14831  int LineSpeedLimit = Track->TrackElementAt(906, VecPos).SpeedLimit01; // speed only in 01 as a continuation
14832  if(TrainStatusInfoOnOffMenuItem->Caption == "Hide Status")
14833  ShowTrainStatusFloatFlag = true;
14834  if(TrainTTInfoOnOffMenuItem->Caption == "Hide Timetable")
14835  ShowTrainTTFloatFlag = true;
14837  {
14840  {
14841  while((CTEIt != TrainController->ContinuationTrainExpectationMultiMap.end()) && ((CTEIt->second.VectorPosition != VecPos) ||
14842  (CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry != NotStarted)))
14843  {
14844  CTEIt++;
14845  }
14847  {
14848  TTrainDataEntry *TTDEPtr = CTEIt->second.TrainDataEntryPtr;
14849  AnsiString ServiceReferenceInfo = "";
14850  // Repeat information
14851  if(TTDEPtr->NumberOfTrains > 1) // Service reference information
14852  {
14853  if(CTEIt->second.RepeatNumber == 0)
14854  {
14855  if(CTEIt->second.HeadCode != TTDEPtr->ServiceReference)
14856  ServiceReferenceInfo = "\nFirst service of ref. " + TTDEPtr->ServiceReference;
14857  else
14858  ServiceReferenceInfo = "\nFirst service";
14859  }
14860  else if(CTEIt->second.HeadCode == TTDEPtr->ServiceReference)
14861  ServiceReferenceInfo = "\nRepeat service no. " + AnsiString(CTEIt->second.RepeatNumber);
14862  else
14863  ServiceReferenceInfo = "\nRepeat service no. " + AnsiString(CTEIt->second.RepeatNumber) + " of ref. " +
14864  TTDEPtr->ServiceReference;
14865  }
14866  else
14867  {
14868  if(CTEIt->second.HeadCode != TTDEPtr->ServiceReference)
14869  ServiceReferenceInfo = "\nService reference " + TTDEPtr->ServiceReference;
14870  }
14871  if(TTDEPtr->ActionVector.at(0).SignallerControl) // entry at 0 is the start entry
14872  {
14873  SpecialStr = "\nTrain under signaller control";
14874  EntrySpeed = TTDEPtr->SignallerSpeed;
14875  if(EntrySpeed > LineSpeedLimit)
14876  EntrySpeed = LineSpeedLimit;
14877  }
14878  else
14879  {
14880  EntrySpeed = TTDEPtr->StartSpeed;
14881  if(EntrySpeed > LineSpeedLimit)
14882  EntrySpeed = LineSpeedLimit;
14883  }
14884  if((CTEIt->first + TDateTime(1.0 / 1440)) < TrainController->TTClockTime) // has to be at least 1 min late to show as late
14885  {
14886  TDateTime TempTime = CTEIt->first;
14887 // need this because CTEIt points to a const object and shouldn't use FormatString on a const object
14888  TrainStatusFloat = CTEIt->second.HeadCode + ": " + CTEIt->second.Description + ServiceReferenceInfo + "\nEntry speed " +
14889  AnsiString::FormatFloat(FormatNoDPStr, EntrySpeed) + "km/h" + SpecialStr + "\nDelayed, was due at " +
14890  Utilities->Format96HHMM(TempTime);
14891  }
14892  else
14893  {
14894  TDateTime TempTime = CTEIt->first;
14895 // need this because CTEIt points to a const object and shouldn't use FormatString on a const object
14896  TrainStatusFloat = CTEIt->second.HeadCode + ": " + CTEIt->second.Description + ServiceReferenceInfo + "\nEntry speed " +
14897  AnsiString::FormatFloat(FormatNoDPStr, EntrySpeed) + "km/h" + SpecialStr + "\nExpected at " +
14898  Utilities->Format96HHMM(TempTime);
14899  }
14900  if(TrainTTInfoOnOffMenuItem->Caption == "Hide Timetable")
14901  {
14902  if(!TTDEPtr->ActionVector.at(0).SignallerControl) // if signaller control there's no timetable & SpecialStr covers this
14903  {
14904  TrainTTFloat = TrainController->ContinuationEntryFloatingTTString(0, TTDEPtr, CTEIt->second.RepeatNumber,
14905  CTEIt->second.IncrementalMinutes, CTEIt->second.IncrementalDigits);
14906  }
14907  }
14908  }
14909  }
14910  }
14911  }
14912  }
14913  }
14914 
14915 // end of TrainFloat section
14916  AnsiString Caption;
14917 
14918  if(!ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
14919  {
14920  FloatingPanel->Visible = false;
14921  Utilities->CallLogPop(1485);
14922  return; // return with label invisible
14923  }
14924  else if(ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
14925  {
14926  Caption = TrackFloat;
14927  }
14928  else if(!ShowTrackFloatFlag && ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
14929  {
14930  Caption = TrainStatusFloat;
14931  }
14932  else if(ShowTrackFloatFlag && ShowTrainStatusFloatFlag && !ShowTrainTTFloatFlag)
14933  {
14934  Caption = TrainStatusFloat + '\n' + '\n' + TrackFloat;
14935  }
14936  else if(!ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
14937  {
14938  if(TrainStatusFloat == "No trains expected")
14939  Caption = TrainStatusFloat;
14940  else
14941  Caption = TrainTTFloat;
14942  }
14943  else if(ShowTrackFloatFlag && !ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
14944  {
14945  if(TrainStatusFloat == "No trains expected")
14946  Caption = TrainStatusFloat + '\n' + '\n' + TrackFloat;
14947  else
14948  Caption = TrainTTFloat + '\n' + '\n' + TrackFloat;
14949  }
14950  else if(!ShowTrackFloatFlag && ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
14951  {
14952  if(TrainStatusFloat == "No trains expected")
14953  Caption = TrainStatusFloat;
14954  else
14955  Caption = TrainStatusFloat + '\n' + '\n' + TrainTTFloat;
14956  }
14957  else if(ShowTrackFloatFlag && ShowTrainStatusFloatFlag && ShowTrainTTFloatFlag)
14958  {
14959  if(TrainStatusFloat == "No trains expected")
14960  Caption = TrainStatusFloat + '\n' + '\n' + TrackFloat;
14961  else
14962  Caption = TrainStatusFloat + '\n' + '\n' + TrainTTFloat + '\n' + '\n' + TrackFloat;
14963  }
14964 
14965  int Left = ScreenX + MainScreen->Left + 16; // so lhs of window is one element to the right of the mouse pos
14966 
14967 // this offset is because window position is relative to the interface form, whereas ScreenX & Y are relative to the MainScreen, which is
14968 // offset 32 to the right and 95 down from the interface form
14969  if((Left + FloatingPanel->Width) > MainScreen->Left + MainScreen->Width)
14970  Left = ScreenX - FloatingPanel->Width + 16; // so rhs of window is one element to the left of the mouse pos (+32 would be at mouse pos)
14971  int Top = ScreenY + MainScreen->Top + 16; // so top of window is one element below the mouse pos (ScreenY + MainScreen->Top would be at mouse pos)
14972 
14973  if((Top + FloatingPanel->Height) > MainScreen->Top + MainScreen->Height)
14974  {
14975  Top = ScreenY - FloatingPanel->Height + 79; // so bottom of window is one element above the mouse pos (95 would be at mouse pos)
14976  // but, top may now be off the top of the screen, if so position at the top of the screen, as always need to see the top, if have to
14977  // lose something then it's best to be from the bottom
14978  if(Top < 30) // use 30 instead of MainScreen->Top [95] as top can go off MainScreen providing it doesn't reach the information panel, as that would
14979  // obscure the window
14980  {
14981  Top = 30;
14982  }
14983  }
14984  if((Left != FloatingPanel->Left) || (Top != FloatingPanel->Top))
14985  {
14986  FloatingPanel->Visible = false; // so doesn't flicker when reposition
14987  FloatingPanel->Left = Left;
14988  FloatingPanel->Top = Top;
14989  Utilities->CallLogPop(1917);
14990  return;
14991  }
14992 
14993  FloatingLabel->Caption = Caption;
14994  FloatingPanel->Visible = true;
14995  FloatingPanel->BringToFront();
14996  Utilities->CallLogPop(746);
14997 }
14998 
14999 // ---------------------------------------------------------------------------
15000 
15001 void TInterface::FlashingGraphics(int Caller, TDateTime Now)
15002  // following section checks to see if GapFlashFlag set & flashes the Gap graphics if so
15003  // Gap flashing is cancelled on any mousedown event
15004 
15005  // deal with flashing GapFlash graphics (only in basic mode so no need to check for trains)
15006 {
15007  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",FlashingGraphics");
15009  {
15010  if(WarningFlash)
15011  {
15012  Track->GapFlashGreen->PlotOverlay(4, Display); // only plotted if PlotOverlay reset
15014  }
15015  else
15016  {
15017  Track->GapFlashGreen->PlotOriginal(17, Display); // only plotted if PlotOverlay set
15019  }
15020  }
15021 
15023  {
15024  if(WarningFlash)
15025  {
15030  Display->Update();
15031  }
15032  else
15033  {
15038  Display->Update();
15039  }
15040  }
15041 
15042 //deal with gap setting - added at v2.6.1 to make location easier
15044  {
15046  }
15048  {
15049  Display->Ellipse(2, Track->GetGapHLoc() * 16, Track->GetGapVLoc() * 16, clB0G0R5);
15050  }
15051 
15053  {
15055  }
15057  {
15058  Display->Ellipse(3, Track->GetGapHLoc() * 16, Track->GetGapVLoc() * 16, clB5G5R5);
15059  }
15060 
15061 // deal with other flashing graphics
15063  {
15064  if((Now - RouteFlashStartTime) < TDateTime(RouteFlashDuration / 86400))
15065  {
15066  // cancel if train is moving & arrives on any part of flashing route
15068  {
15069  Track->RouteFlashFlag = false;
15071  ClearandRebuildRailway(18); // because using ConstructRoute->RouteFlash.PlotOriginal() can plot wrong point fillet as well as
15072  // original (if proposed route would change point). With this can dispense with ConstructRoute->RouteFlash.PlotOriginal()
15073  Utilities->CallLogPop(75);
15074  return;
15075  }
15076 
15077  InfoPanel->Visible = true;
15078  if(Level2OperMode == PreStart)
15079  InfoPanel->Caption = "PRE-START: Route setting in progress";
15080  else
15081  InfoPanel->Caption = "OPERATING: Route setting in progress";
15082  if(WarningFlash)
15083  {
15085  }
15086  else
15087  {
15089  }
15090  }
15091  else
15092  {
15093 // ConstructRoute->RouteFlash.PlotOriginal(); don't need with clearand....
15094 // stop clock while converting route as can take several seconds
15095  TrainController->StopTTClockFlag = true; // so TTClock stopped during MasterClockTimer function
15097  if(PreferredRouteFlag)
15099  else
15101  ConstructRoute->ClearRoute(); // clear it immediately after use so as not to clutter the errorlog
15102  TrainController->BaseTime = TDateTime::CurrentDateTime();
15104  Track->RouteFlashFlag = false;
15106  ClearandRebuildRailway(19); // if drop this ensure replot trains after replot routes else route will overwrite a train
15107  }
15108  }
15109 
15110  if(Track->RouteFlashFlag && Display->ZoomOutFlag) // must have entered RouteFlash from normal screen so button states stored
15111  // dropped ZoomOutButton when route or point flashing, but leave this section in in case need to reinstate
15112  // no need to call Clearand... as that is called when revert to normal mode
15113  {
15114  if((Now - RouteFlashStartTime) >= TDateTime(RouteFlashDuration / 86400))
15115  {
15116  Track->RouteFlashFlag = false;
15117  if(PreferredRouteFlag)
15118  {
15120  }
15121  else
15122  {
15124  }
15125  ConstructRoute->ClearRoute(); // clear it immediately after use so as not to clutter the errorlog
15126  }
15127  }
15128 
15130  {
15131  if((Now - PointFlashStartTime) < TDateTime((PointsFlashDuration) / 86400))
15132  {
15133  // cancel if train is present on or enters a flashing point, either selected or diverging
15135  {
15137  Track->PointFlashFlag = false;
15139  Utilities->CallLogPop(76);
15140  return;
15141  }
15143  {
15145  Track->PointFlashFlag = false;
15147  Utilities->CallLogPop(77);
15148  return;
15149  }
15150 
15151  if(WarningFlash)
15152  {
15155  }
15156  else
15157  {
15159  }
15160  }
15161  else
15162  {
15167  {
15171  }
15173  Display->Update(); // resurrected when Update() dropped from PlotOutput etc
15174  Track->PointFlashFlag = false;
15176  }
15177  }
15178 
15180  // dropped ZoomOutButton when point flashing but leave this section in in case need to reinstate
15181  {
15182  if((Now - PointFlashStartTime) < TDateTime((PointsFlashDuration) / 86400))
15183  {
15187  {
15190  }
15191  Track->PointFlashFlag = false;
15193  }
15194  }
15195 // deal with level crossings
15196  if(!Track->ChangingLCVector.empty() && (Level2OperMode != Paused))
15197  {
15198  int H;
15199  int V;
15200 
15201  for(unsigned int x = 0; x < Track->ChangingLCVector.size(); x++)
15202  {
15203  bool Manual = false;
15204  if(Track->ChangingLCVector.at(x).ConsecSignals == 2) //manual
15205  {
15206  Manual = true;
15207  }
15208  H = Track->ChangingLCVector.at(x).HLoc;
15209  V = Track->ChangingLCVector.at(x).VLoc;
15210  if((Now - Track->ChangingLCVector.at(x).StartTime) < TDateTime((Track->ChangingLCVector.at(x).ChangeDuration) / 86400))
15211  // still flashing
15212  {
15213  if(WarningFlash)
15214  {
15215  if(Track->ChangingLCVector.at(x).BarrierState == TTrack::Raising) // closing to trains
15216  {
15217  Track->PlotRaisedLinkedLevelCrossingBarriers(1, Track->ChangingLCVector.at(x).BaseElementSpeedTag, H, V, Display); //always plots red when raising
15218  }
15219  else
15220  {
15221  Track->PlotLoweredLinkedLevelCrossingBarriers(0, Track->ChangingLCVector.at(x).BaseElementSpeedTag, H, V,
15222  Track->ChangingLCVector.at(x).ConsecSignals, Display, Manual);
15223  }
15224  }
15225  else
15226  {
15227  Track->PlotLCBaseElementsOnly(2, Track->ChangingLCVector.at(x).BarrierState, Track->ChangingLCVector.at(x).BaseElementSpeedTag, H, V,
15228  Track->ChangingLCVector.at(x).ConsecSignals, Display);
15229  }
15230  }
15231  else
15232  // flashing period finished
15233  {
15234  if(Track->ChangingLCVector.at(x).BarrierState == TTrack::Raising)
15235  {
15236  Track->PlotRaisedLinkedLevelCrossingBarriers(2, Track->ChangingLCVector.at(x).BaseElementSpeedTag, H, V, Display); //always plot red when fully raised
15237  Track->SetLinkedLevelCrossingBarrierAttributes(4, H, V, 0); // only set attr to 0 when fully raised
15238  // attributes set to 2 when changing state, now reset to 0, no other actions needed
15239  }
15240  else
15241  // barriers lowering
15242  {
15243  Track->PlotLoweredLinkedLevelCrossingBarriers(1, Track->ChangingLCVector.at(x).BaseElementSpeedTag, H, V,
15244  Track->ChangingLCVector.at(x).ConsecSignals, Display, Manual);
15245  Track->SetLinkedLevelCrossingBarrierAttributes(5, H, V, 1); // only set attr to 1 when fully lowered
15246  bool FoundFlag;
15247  int TVPos = Track->GetVectorPositionFromTrackMap(46, H, V, FoundFlag);
15248  if(!FoundFlag)
15249  {
15250  throw Exception("Failed to find a route at LC position HLoc = " + (AnsiString)H + " VLoc = " + (AnsiString)V);
15251  }
15252  int RouteNumber;
15253  AllRoutes->GetRouteTypeAndNumber(24, TVPos, 0, RouteNumber); // use 0 for LinkPos, could be 1 or 0 as only a single track element
15254  // don't need returned value of RouteType
15255  if(RouteNumber > -1) // if train crashed then there won't be a routenumber
15256  {
15257  AllRoutes->GetFixedRouteAt(196, RouteNumber).SetRouteSignals(8);
15258  }
15259  }
15260  }
15261  }
15262  for(int x = Track->ChangingLCVector.size() - 1; x >= 0; x--)
15263  // now transfer lowering barrier object from the ChangingLCVector to the BarriersDownVector if lowering, reset the start timer (to time the barrier down period)
15264  // and for either raising or lowering erase the object from the ChangingLCVector
15265  {
15266  if(!Track->IsLCBarrierFlashingAtHV(0, Track->ChangingLCVector.at(x).HLoc, Track->ChangingLCVector.at(x).VLoc))
15267  {
15268  if(Track->ChangingLCVector.at(x).BarrierState == TTrack::Lowering)
15269  {
15270  Track->ChangingLCVector.at(x).StartTime = TrainController->TTClockTime;
15271  Track->ChangingLCVector.at(x).BarrierState = TTrack::Down;
15272  Track->BarriersDownVector.push_back(Track->ChangingLCVector.at(x));
15273  }
15274  Track->ChangingLCVector.erase(Track->ChangingLCVector.begin() + x);
15275  }
15276  }
15277  }
15278  Utilities->CallLogPop(747);
15279 }
15280 
15281 // ---------------------------------------------------------------------------
15282 
15284  // set boundary, Home, NewHome, ZoomOut, CallingOn buttons & menu items as appropriate
15285 {
15286  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetSaveMenuAndButtons");
15287 
15288 // set save railway buttons
15289  bool SaveRailwayButtonsFlag = true;
15290 
15291  SaveRailwayTBPButton->Visible = true;
15292  SaveRailwayPDPButton->Visible = true;
15293  SaveSessionButton->Visible = true;
15294  if(Level1Mode == OperMode)
15295  {
15297  {
15298  SaveRailwayButtonsFlag = false;
15299  }
15300  // set PresetAutoSigRoutesButton enabled or not
15301  // enable if PreStart & no routes set
15302  if((Level2OperMode == PreStart) && (AllRoutes->AllRoutesVector.empty()))
15303  {
15304  PresetAutoSigRoutesButton->Enabled = true;
15305  }
15306  else
15307  {
15308  PresetAutoSigRoutesButton->Enabled = false;
15309  }
15310  }
15311  else
15312  {
15314  {
15315  SaveRailwayButtonsFlag = false;
15316  }
15317  else if(SavedFileName != "")
15318  {
15319  if((SavedFileName[SavedFileName.Length()] == 'y') || (SavedFileName[SavedFileName.Length()] == 'Y')) // 'rly' file
15320  {
15321  if(!(Track->IsReadyForOperation(false)))
15322  {
15323  SaveRailwayButtonsFlag = false; // can't save under its old name as not now a .rly file
15324  }
15325  }
15326  }
15327  }
15328  if(SaveRailwayButtonsFlag && (Level1Mode == BaseMode))
15329  {
15330  SaveRailwayBaseModeButton->Visible = true;
15331  }
15332  else
15333  {
15334  SaveRailwayBaseModeButton->Visible = false;
15335  }
15336  SaveRailwayTBPButton->Enabled = SaveRailwayButtonsFlag;
15337  SaveRailwayPDPButton->Enabled = SaveRailwayButtonsFlag;
15338  SaveRailwayBaseModeButton->Enabled = SaveRailwayButtonsFlag;
15339  SaveSessionButton->Enabled = SaveRailwayButtonsFlag;
15340 
15341 // set formatted timetable menu item
15342  if(TimetableTitle == "")
15343  {
15344  ExportTTMenuItem->Enabled = false;
15345  }
15346  else
15347  {
15348  ExportTTMenuItem->Enabled = true;
15349  }
15350 
15351 // set info menu items
15353  {
15354  FloatingInfoMenu->Enabled = false;
15355  TrackInfoMenuItem->Enabled = false;
15356  TrainInfoMenuItem->Enabled = false;
15357  }
15358  else
15359  {
15360  FloatingInfoMenu->Enabled = true;
15361  TrackInfoMenuItem->Enabled = true;
15362  if(Level1Mode == OperMode)
15363  {
15364  TrainInfoMenuItem->Enabled = true;
15365  }
15366  else
15367  {
15368  TrainInfoMenuItem->Enabled = false;
15369  }
15370  }
15371 
15372 // set all bar CallingOnButton operational to begin with - no, causes flickering of button graphics,
15373 // work on internal flags & then set buttons according to final flag values, then graphic won't change unless
15374 // there has been a legitimate change of state since the last access
15375 
15376  bool ZoomFlag = true, HomeFlag = true, NewHomeFlag = true, ScreenLeftFlag = true, ScreenRightFlag = true, ScreenUpFlag = true, ScreenDownFlag = true,
15377  TrackBuildPanelEnabledFlag = true, PrefDirPanelEnabledFlag = true, OperatingPanelEnabledFlag = true, TimetablePanelEnabledFlag = true;
15378 
15379  AnsiString TrackBuildPanelLabelCaptionStr = "Build/modify";
15380  AnsiString PrefDirPanelLabelCaptionStr = "Preferred direction selection";
15381  AnsiString OperatingPanelLabelCaptionStr = "Operation";
15382  AnsiString TimetablePanelLabelCaptionStr = "Timetable editor";
15383 
15384  if(!Display->ZoomOutFlag)
15385  { // prevent if half a screen or less visible (width = 60, height = 36) [Note HLocMin & Max 1 greater than extreme element]
15387  ScreenLeftFlag = false; // 60 - 30
15389  ScreenRightFlag = false; // 60 - (60 - 30)
15391  ScreenUpFlag = false; // 36 - 18
15393  ScreenDownFlag = false; // 36 - (36 - 18)
15394  }
15395  else
15396  { // prevent if less than a quarter of a screen visible (width = 240, height = 144)
15398  ScreenLeftFlag = false; // 240 - 60
15400  ScreenRightFlag = false; // 240 - (240 - 60)
15402  ScreenUpFlag = false; // 144 - 36
15404  ScreenDownFlag = false; // 144 - (144 - 36)
15405  }
15407  {
15408  ZoomFlag = false;
15409  HomeFlag = false;
15410  NewHomeFlag = false;
15411  ScreenLeftFlag = false;
15412  ScreenRightFlag = false;
15413  ScreenUpFlag = false;
15414  ScreenDownFlag = false;
15415  }
15416 
15417  if(Display->ZoomOutFlag)
15418  {
15419 // NewHomeFlag = false;
15420  TrackBuildPanelEnabledFlag = false;
15421  TrackBuildPanelLabelCaptionStr = "Disabled";
15422  PrefDirPanelEnabledFlag = false;
15423  PrefDirPanelLabelCaptionStr = "Disabled";
15424  OperatingPanelEnabledFlag = false;
15425  OperatingPanelLabelCaptionStr = "Disabled";
15426  TimetablePanelEnabledFlag = false;
15427  TimetablePanelLabelCaptionStr = "Disabled";
15428  }
15429 
15430  if(Level1Mode == OperMode)
15431  {
15432  if(Track->RouteFlashFlag || Track->PointFlashFlag || TTClockAdjPanel->Visible == true || TTClockAdjustWarningPanel->Visible == true) //TTClockAdjPanel added for v2.4.2 to keep it disabled after Clock2Stopped dropped
15433  {
15434  MTBFEditBox->Enabled = false;
15435  OperatingPanelEnabledFlag = false;
15436  OperatingPanelLabelCaptionStr = "Disabled";
15437  ZoomFlag = false;
15438  HomeFlag = false;
15439  NewHomeFlag = false;
15440  ScreenLeftFlag = false;
15441  ScreenRightFlag = false;
15442  ScreenUpFlag = false;
15443  ScreenDownFlag = false;
15444  SaveOperatingImageMenuItem->Enabled = false;
15445  }
15446  else
15447  {
15448  MTBFEditBox->Enabled = true;
15449  SaveOperatingImageMenuItem->Enabled = true;
15450  }
15451  }
15452 
15453  if(LocationNameTextBox->Visible)
15454  {
15455  ZoomFlag = false;
15456  HomeFlag = false;
15457  NewHomeFlag = false;
15458  ScreenLeftFlag = false;
15459  ScreenRightFlag = false;
15460  ScreenUpFlag = false;
15461  ScreenDownFlag = false;
15462  }
15463 
15464  if(TextBox->Visible) // added at v1.3.0 to prevent screen moving when movement keys pressed during text entry
15465  {
15466  ZoomFlag = false;
15467  HomeFlag = false;
15468  NewHomeFlag = false;
15469  ScreenLeftFlag = false;
15470  ScreenRightFlag = false;
15471  ScreenUpFlag = false;
15472  ScreenDownFlag = false;
15473  }
15474 
15475  if((Level1Mode == TimetableMode) && (TimetableEditPanel->Visible))
15476  // added at v1.3.0 to prevent screen moving when movement keys pressed during timetable compilation (allowed if TT hidden)
15477  {
15478  ZoomFlag = false;
15479  HomeFlag = false;
15480  NewHomeFlag = false;
15481  ScreenLeftFlag = false;
15482  ScreenRightFlag = false;
15483  ScreenUpFlag = false;
15484  ScreenDownFlag = false;
15485  }
15486 
15489  {
15490  ZoomFlag = false;
15491  }
15492 
15493  if(ZoomFlag)
15494  ZoomButton->Enabled = true;
15495  else
15496  ZoomButton->Enabled = false;
15497  if(HomeFlag)
15498  HomeButton->Enabled = true;
15499  else
15500  HomeButton->Enabled = false;
15501  if(NewHomeFlag)
15502  NewHomeButton->Enabled = true;
15503  else
15504  NewHomeButton->Enabled = false;
15505  if(ScreenLeftFlag)
15506  ScreenLeftButton->Enabled = true;
15507  else
15508  ScreenLeftButton->Enabled = false;
15509  if(ScreenRightFlag)
15510  ScreenRightButton->Enabled = true;
15511  else
15512  ScreenRightButton->Enabled = false;
15513  if(ScreenUpFlag)
15514  ScreenUpButton->Enabled = true;
15515  else
15516  ScreenUpButton->Enabled = false;
15517  if(ScreenDownFlag)
15518  ScreenDownButton->Enabled = true;
15519  else
15520  ScreenDownButton->Enabled = false;
15521  if(OperatingPanelEnabledFlag)
15522  OperatingPanel->Enabled = true;
15523  else
15524  OperatingPanel->Enabled = false;
15525  if(TrackBuildPanelEnabledFlag)
15526  TrackBuildPanel->Enabled = true;
15527  else
15528  TrackBuildPanel->Enabled = false;
15529  if(PrefDirPanelEnabledFlag)
15530  PrefDirPanel->Enabled = true;
15531  else
15532  PrefDirPanel->Enabled = false;
15533  if(TimetablePanelEnabledFlag)
15534  TimetablePanel->Enabled = true;
15535  else
15536  TimetablePanel->Enabled = false;
15537  TrackBuildPanelLabel->Caption = TrackBuildPanelLabelCaptionStr;
15538  PrefDirPanelLabel->Caption = PrefDirPanelLabelCaptionStr;
15539  OperatingPanelLabel->Caption = OperatingPanelLabelCaptionStr;
15540  TimetablePanelLabel->Caption = TimetablePanelLabelCaptionStr;
15541 
15542 // check if any CallingOnFlags set & set button accordingly
15543  if(Display->ZoomOutFlag)
15544  {
15545  CallingOnButton->Enabled = false;
15546  CallingOnButton->Down = false;
15547  }
15548  else
15549  {
15550  if(Level2OperMode == Operating)
15551  {
15552  bool CallOnValid = false;
15553  for(unsigned int x = 0; x < TrainController->TrainVector.size(); x++)
15554  {
15556  {
15557  CallingOnButton->Enabled = true;
15558  CallOnValid = true;
15559  }
15560  }
15561  if(!CallOnValid)
15562  {
15563  CallingOnButton->Enabled = false;
15564  CallingOnButton->Down = false;
15565  }
15566  }
15567  else
15568  {
15569  CallingOnButton->Enabled = false;
15570  CallingOnButton->Down = false;
15571  }
15572  }
15573  Utilities->CallLogPop(970);
15574 }
15575 
15576 // ---------------------------------------------------------------------------
15577 
15578 void TInterface::ErrorLog(int Caller, AnsiString Message)
15579 {
15580 // create an error file for diagnostic purposes called on detection of a runtime error
15581 
15582 // Note: For faults in ClockTimer2, after the catch block in ClockTimer2 which calls this function, execution continues from where
15583 // ClockTimer2 was called, so the Utilities->Clock2Stopped flag is cleared and the whole sequence repeats itself, including the fault, until
15584 // the user presses the Exit button. Note also that Utilities->CallLogPop, called when ClockTimer (not ClockTimer2) returns, pops the error
15585 // message off the back of the Utilities->CallLog, not the ClockTimer call. Hence entries keep stacking up, including the push_front entry
15586 // but not the push_back error entry, and when finally printed there is a whole series of entries for the one fault, the number
15587 // depending on the time taken to press Exit.
15588 // Hence introduce an ErrorLogCalledFlag, set to true on first call, and preventing further calls thereafter.
15589 
15590  if(ErrorLogCalledFlag)
15591  return;
15592 
15593  ErrorLogCalledFlag = true;
15594  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + "," + Message);
15595  Utilities->CallLog.push_front("Version: " + ProgramVersion + "; Time and date: " + Utilities->DateTimeStamp());
15596  SaveErrorFile();
15597  if((TempTTFileName != "") && FileExists(TempTTFileName))
15598  {
15599  DeleteFile(TempTTFileName);
15600  }
15601  Display->GetImage()->Visible = false;
15602  PerformancePanel->Visible = false;
15603  OperatorActionPanel->Visible = false; // new v2.2.0
15604  TrackBuildPanel->Visible = false;
15605  TrackElementPanel->Visible = false;
15606  LocationNameTextBox->Visible = false;
15607  TextBox->Visible = false;
15608  TrackLengthPanel->Visible = false;
15609  InfoPanel->Visible = false;
15610  PrefDirPanel->Visible = false;
15611  TimetablePanel->Visible = false;
15612  TimetableEditPanel->Visible = false;
15613  TrainController->TTEditPanelVisible = false; //added at v2.6.0 for two location message
15614  OperatingPanel->Visible = false;
15615  FloatingPanel->Visible = false;
15616  ModeMenu->Enabled = false;
15617  SigImagePanel->Visible = false; // new at v2.3.0
15618  FileMenu->Enabled = false;
15619  EditMenu->Enabled = false;
15620  FloatingInfoMenu->Enabled = false;
15621  HelpMenu->Enabled = false;
15622 // SaveHeaderMenu1->Enabled = false;
15623  ScreenLeftButton->Visible = false;
15624  ScreenRightButton->Visible = false;
15625  ScreenUpButton->Visible = false;
15626  ScreenDownButton->Visible = false;
15627  HomeButton->Visible = false;
15628  NewHomeButton->Visible = false;
15629  ZoomButton->Visible = false;
15630  PrefDirKey->Visible = false;
15631  DistanceKey->Visible = false;
15632  OutputLog1->Caption = "";
15633  OutputLog2->Caption = "";
15634  OutputLog3->Caption = "";
15635  OutputLog4->Caption = "";
15636  OutputLog5->Caption = "";
15637  OutputLog6->Caption = "";
15638  OutputLog7->Caption = "";
15639  OutputLog8->Caption = "";
15640  OutputLog9->Caption = "";
15641  OutputLog10->Caption = "";
15642  if(Caller == 113)
15643  {
15644  ErrorMessageStoreImage->Visible = true;
15645  }
15646  else
15647  {
15648  ErrorMessage->Visible = true;
15649  }
15650  ErrorButton->Visible = true;
15651  Screen->Cursor = TCursor(-2); // Arrow; - in case was an hourglass
15652 // No need for Utilities->CallLogPop as the call log deque has already been written to file & the next action
15653 // is to close the program when the exit button is pressed
15654 }
15655 
15656 // ---------------------------------------------------------------------------
15657 
15659  // not used from v2.2.0 as now allow floating panel & label to overlie performance panel
15660 {
15661  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",IsPerformancePanelObscuringFloatingLabel");
15662  if(FloatingPanel->Visible == false)
15663  {
15664  Utilities->CallLogPop(1205);
15665  return false;
15666  }
15667 // pptop >= flbot, ppbot <= fltop, ppleft >= flright, ppright <= flleft
15668  if((PerformancePanel->Top >= (FloatingPanel->Top + FloatingPanel->Height)) || ((PerformancePanel->Top + PerformancePanel->Height) <= FloatingPanel->Top) ||
15669  (PerformancePanel->Left >= (FloatingPanel->Left + FloatingPanel->Width)) || ((PerformancePanel->Left + PerformancePanel->Width) <= FloatingPanel->Left))
15670  {
15671  Utilities->CallLogPop(1206);
15672  return false;
15673  }
15674  else
15675  {
15676  Utilities->CallLogPop(1207);
15677  return true;
15678  }
15679 }
15680 // ---------------------------------------------------------------------------
15681 
15682 void TInterface::SetCaption(int Caller)
15683 {
15684 /*
15685  NamedRailway; RlyFile; NamedTimetable
15686  n x x "New railway under development";
15687  y n x RailwayTitle + ": under development";
15688  y y n RailwayTitle + ": no timetable loaded";
15689  y y y RailwayTitle + ", " + TimetableTitle;
15690 */
15691 
15692  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetCaption");
15693  if(RailwayTitle == "")
15694  Caption = "Railway: New railway under development";
15695  else if(!RlyFile)
15696  Caption = "Railway: " + RailwayTitle + " under development";
15697 // else if(TimetableTitle == "") Caption = "Railway: " + RailwayTitle + "; Timetable: none loaded";
15698  else if(TimetableTitle == "")
15699  Caption = "Railway: " + RailwayTitle; // changed at v2.1.0, no need to mention TT if none loaded
15700  else
15701  Caption = "Railway: " + RailwayTitle + "; Timetable: " + TimetableTitle;
15702  Utilities->CallLogPop(1208);
15703 }
15704 
15705 // ---------------------------------------------------------------------------
15706 
15707 void TInterface::ResetAll(int Caller)
15708 {
15709  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ResetAll");
15710  LastNonCtrlOrShiftKeyDown = -1; // added at v2.4.2 to no key down
15712  Track->GapFlashRedPosition = -1;
15713  Track->GapFlashFlag = false;
15714  Track->RouteFlashFlag = false;
15715  Track->PointFlashFlag = false;
15717  AutoSigsFlag = false;
15718  PreventGapOffsetResetting = false;
15719 
15720  Utilities->Clock2Stopped = false;
15721  TTClockSpeed = 1;
15722  TTClockSpeedLabel->Caption = "x1";
15723  Track->SetTrackFinished(false);
15725  CurrentSpeedButton = 0; // not assigned yet
15727  StartX = 0;
15728  StartY = 0;
15729  mbLeftDown = false;
15731  TextOrUserGraphicGridButton->Glyph->LoadFromResourceName(0, "PixelPrecision1");
15733  SigAspectButton->Glyph->LoadFromResourceName(0, "FourAspect");
15735  WarningFlashCount = 0;
15736 
15737  Level1Mode = BaseMode;
15738  SetLevel1Mode(26);
15739  RouteMode = None;
15740  PreferredRoute = true;
15741  ConsecSignalsRoute = true;
15742  DevelopmentPanel->Visible = false;
15743 
15744  MainScreen->Canvas->CopyMode = cmSrcCopy;
15745  FloatingPanel->Visible = false;
15746  OverallDistance = 0;
15747  OverallSpeedLimit = -1;
15748  AllRoutes->RouteTruncateFlag = false;
15749  CallingOnButton->Down = false;
15750  Display->ZoomOutFlag = false;
15751  ScreenGridFlag = false;
15752  InfoCaptionStore = "";
15753  ErrorLogCalledFlag = false;
15754  ErrorMessage->Visible = false;
15755  ErrorMessageStoreImage->Visible = false;
15756  TempCursorSet = false;
15757  TempCursor = TCursor(-2); // Arrow
15758  WholeRailwayMoving = false; // new at v2.1.0
15759 
15760  TrainController->TTClockTime = TDateTime(0); // default setting
15761  TTClockAdjPanel->Visible = false;
15763  ConflictPanel->Visible = false;
15764  SelectedTrainID = -1;
15765  SetTrackBuildImages(11);
15766 // TrackInfoOnOffMenuItem->Caption = "Show"; dropped these here at v1.2.0 so don't reset when load a session file
15767 // TrainStatusInfoOnOffMenuItem->Caption = "Show Status";
15768 // TrainTTInfoOnOffMenuItem->Caption = "Show Timetable";
15769  Track->CalcHLocMinEtc(8);
15770  FileChangedFlag = false;
15771  RlyFile = false;
15772  SaveSessionFlag = false;
15773  LoadSessionFlag = false;
15774  SelectionValid = false;
15775  TimetableChangedFlag = false;
15776  SavedFileName = "";
15777  RailwayTitle = "";
15778  TimetableTitle = "";
15779  SetCaption(1);
15780  CreateEditTTFileName = ""; // set to null to allow a check during error file saving, if not null save the tt being edited to the file
15781  // added for Beta v0.2b
15782  CreateEditTTTitle = ""; // as above
15783  AllRoutes->NextRouteID = 0;
15784  TTrain::NextTrainID = 0; // reset to 0 whenever enter operating mode
15785  TFont *TempFont = new TFont; // if try to alter MainScreen->Canvas->Font directly it won't change the style for some reason
15786 
15787  TempFont->Style.Clear();
15788  TempFont->Name = "MS Sans Serif"; // reset font, else stays set to last displayed text font
15789  TempFont->Size = 10;
15790  TempFont->Color = clB0G0R0;
15791  TempFont->Charset = (TFontCharset)(0);
15792  MainScreen->Canvas->Font->Assign(TempFont);
15793  PerformancePanel->Top = MainScreen->Top + MainScreen->Height - PerformancePanel->Height;
15794  PerformancePanel->Left = MainScreen->Left;
15795  OperatorActionPanel->Top = MainScreen->Top + MainScreen->Height - OperatorActionPanel->Height; // new v2.2.0
15796  OperatorActionPanel->Left = MainScreen->Left + MainScreen->Width - OperatorActionPanel->Width; ; // new v2.2.0
15797  // ScreenRightButton->Left = MainScreen->Width + MainScreen->Left; //Button values changed at v2.1.0 to allow for screen resizing
15798  // ScreenLeftButton->Left = ScreenRightButton->Left;
15799  // ScreenUpButton->Left = ScreenRightButton->Left;
15800  // ScreenDownButton->Left = ScreenRightButton->Left;
15801  // HomeButton->Left = ScreenRightButton->Left;
15802  // NewHomeButton->Left = ScreenRightButton->Left;
15803  // ZoomButton->Left = ScreenRightButton->Left;
15804  DevelopmentPanel->Top = MainScreen->Top + MainScreen->Height - DevelopmentPanel->Height;
15805  DevelopmentPanel->Left = MainScreen->Left + MainScreen->Width - DevelopmentPanel->Width; ; // new v2.2.0
15806 
15807  delete TempFont;
15808  CtrlKey = false;
15809  ShiftKey = false;
15810  Utilities->CallLogPop(1209);
15811 }
15812 
15813 // ---------------------------------------------------------------------------
15814 
15816 {
15817  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetTrackBuildImages,");
15818  if((Level1Mode == OperMode) || RlyFile)
15819  {
15820  TrackLinkedImage->Visible = false;
15821  TrackNotLinkedImage->Visible = false;
15822  GapsSetImage->Visible = false;
15823  GapsNotSetImage->Visible = false;
15824  LocationNamesSetImage->Visible = false;
15825  LocationNamesNotSetImage->Visible = false;
15826  Utilities->CallLogPop(1114);
15827  return;
15828  }
15829  else
15830  {
15831  if(!Track->NoActiveTrack(9))
15832  {
15833  if(Track->IsTrackFinished())
15834  {
15835  TrackLinkedImage->Visible = true;
15836  TrackNotLinkedImage->Visible = false;
15837  }
15838  else
15839  {
15840  TrackNotLinkedImage->Visible = true;
15841  TrackLinkedImage->Visible = false;
15842  }
15843  }
15844  else
15845  {
15846  TrackLinkedImage->Visible = false;
15847  TrackNotLinkedImage->Visible = false;
15848  }
15849 
15850  if(!Track->NoGaps(1))
15851  {
15852  if(Track->GapsUnset(6))
15853  {
15854  GapsNotSetImage->Visible = true;
15855  GapsSetImage->Visible = false;
15856  }
15857  else
15858  {
15859  GapsNotSetImage->Visible = false;
15860  GapsSetImage->Visible = true;
15861  }
15862  }
15863  else
15864  {
15865  GapsNotSetImage->Visible = false;
15866  GapsSetImage->Visible = false;
15867  }
15868 
15870  {
15871  if(Track->LocationsNotNamed(0))
15872  {
15873  LocationNamesSetImage->Visible = false;
15874  LocationNamesNotSetImage->Visible = true;
15875  }
15876  else
15877  {
15878  LocationNamesSetImage->Visible = true;
15879  LocationNamesNotSetImage->Visible = false;
15880  }
15881  }
15882  else
15883  {
15884  LocationNamesSetImage->Visible = false;
15885  LocationNamesNotSetImage->Visible = false;
15886  }
15887  }
15888  Utilities->CallLogPop(1113);
15889 }
15890 
15891 // ---------------------------------------------------------------------------
15892 
15893 void TInterface::ResetChangedFileDataAndCaption(int Caller, bool NonPrefDirChangesMade)
15894 {
15895  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",ResetChangedFileDataAndCaption");
15896  FileChangedFlag = true;
15897  if(NonPrefDirChangesMade)
15898  {
15899  if(RlyFile) // i.e. was a Railway file but major changes made so class as a new railway
15900  {
15901  RailwayTitle = "";
15902  TimetableTitle = "";
15903  SavedFileName = "";
15904  RlyFile = false;
15905  }
15906  TimetableTitle = ""; // should have been reset already during user mode change but include here also
15907  SetTrackBuildImages(15);
15908  }
15909  SetCaption(2);
15910  Utilities->CallLogPop(1210);
15911 }
15912 
15913 // ---------------------------------------------------------------------------
15914 
15915 void TInterface::SaveSession(int Caller)
15916 { // ExcessLCDownMins saved as string after ***Interface*** see below
15917  try
15918  {
15919  TrainController->LogEvent("SaveSession");
15920  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveSession");
15921  AnsiString CurrentDateTimeStr = "", TimetableTimeStr = "", SessionFileStr = "";
15922  Screen->Cursor = TCursor(-11); // Hourglass;
15923  CurrentDateTimeStr = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
15924  // avoid characters in filename:= / \ : * ? " < > |
15925  TimetableTimeStr = Utilities->Format96HHMMSS(TrainController->TTClockTime);
15926  TimetableTimeStr = TimetableTimeStr.SubString(1, 2) + '.' + TimetableTimeStr.SubString(4, 2) + '.' + TimetableTimeStr.SubString(7, 2);
15927 // SessionFileStr = CurDir + "\\" + SESSION_DIR_NAME + "\\Session " + CurrentDateTimeStr + "; Timetable time " + TimetableTimeStr + "; " + RailwayTitle +
15928 // "; " + TimetableTitle + ".ssn";
15929  SessionFileStr = LoadSessionDialog->InitialDir + "\\Session " + CurrentDateTimeStr + "; Timetable time " + TimetableTimeStr + "; " + RailwayTitle +
15930  "; " + TimetableTitle + ".ssn";
15931  std::ofstream SessionFile(SessionFileStr.c_str());
15932  if(!(SessionFile.fail()))
15933  {
15934  Utilities->SaveFileString(SessionFile, ProgramVersion + ": ***Interface***" + FloatToStr(TrainController->ExcessLCDownMins));
15935 // added ExcessLC... at v2.2.0 as omitted earlier
15936  SaveInterface(0, SessionFile);
15937  // save track elements
15938  Utilities->SaveFileString(SessionFile, "***Track***");
15939  if(Track->UserGraphicVector.empty())
15940  {
15941  Track->SaveTrack(4, SessionFile, false); // false for no graphics (**Active elements** saved as marker)
15942  }
15943  else
15944  {
15945  Track->SaveTrack(11, SessionFile, true); // true for graphics to be saved (**Active elements**1 saved as marker)
15946  }
15947  // save text elements
15948  Utilities->SaveFileString(SessionFile, "***Text***");
15949  TextHandler->SaveText(2, SessionFile);
15950  // save PrefDir elements
15951  Utilities->SaveFileString(SessionFile, "***PrefDirs***");
15952  EveryPrefDir->SavePrefDirVector(2, SessionFile);
15953  if(!Track->UserGraphicVector.empty())
15954  {
15955  // save user graphics
15956  Track->SaveUserGraphics(2, SessionFile);
15957  }
15958  // save routes
15959  Utilities->SaveFileString(SessionFile, "***Routes***");
15960  AllRoutes->SaveRoutes(0, SessionFile);
15961  // save LockedRoutes
15962  Utilities->SaveFileString(SessionFile, "***Locked routes***");
15963  TrainController->SaveSessionLockedRoutes(0, SessionFile);
15964  // save ContinuationAutoSigEntries
15965  Utilities->SaveFileString(SessionFile, "***ContinuationAutoSigEntries***");
15967  // save BarriersDownVector
15968  Utilities->SaveFileString(SessionFile, "***BarriersDownVector***");
15969  Track->SaveSessionBarriersDownVector(0, SessionFile);
15970  // save timetable
15971  Utilities->SaveFileString(SessionFile, "***Timetable***");
15972  if(!(SaveTimetableToSessionFile(0, SessionFile, SessionFileStr)))
15973  {
15974  SessionFile.close();
15975  DeleteFile(SessionFileStr);
15976  Screen->Cursor = TCursor(-2); // Arrow;
15977  TrainController->StopTTClockMessage(3, "Error saving file, unable to save session");
15978  Utilities->CallLogPop(1150);
15979  return;
15980  }
15981  // save TimetableClock
15982  Utilities->SaveFileString(SessionFile, "***TimetableClock***");
15983  Utilities->SaveFileDouble(SessionFile, double(TrainController->TTClockTime));
15984 
15985  // save trains
15986  Utilities->SaveFileString(SessionFile, "***Trains***");
15987  TrainController->SaveSessionTrains(0, SessionFile);
15988  // save performance file
15989  Utilities->SaveFileString(SessionFile, "***Performance file***");
15990  SavePerformanceFile(0, SessionFile);
15991  Utilities->SaveFileString(SessionFile, "***End of performance file***");
15992 // addition at v2.4.0 to save TrainController->AvHoursIntValue + any future additions
15993  Utilities->SaveFileString(SessionFile, "***Additions after v2.3.1***");
15996  Utilities->SaveFileString(SessionFile, "***Failed Trains***");
15997  for(unsigned int x = 0; x < TrainController->TrainVector.size(); x++)
15998  {
16000  {
16003  }
16004  }
16005  Utilities->SaveFileInt(SessionFile, -1); // marker for end of failed trains
16006  Utilities->SaveFileString(SessionFile, "End of file at v2.4.0");
16007 // end of v2.4.0 addition
16008  SessionFile.close();
16009  TrainController->StopTTClockMessage(4, "Session saved: Session " + CurrentDateTimeStr + "; Timetable time " + TimetableTimeStr + "; " +
16010  RailwayTitle + "; " + TimetableTitle + ".ssn");
16011  LastNonCtrlOrShiftKeyDown = -1; //to restore the ability to reselect Ctrl S after a save (FormKeyUp doesn't work because the Interface form doesn't have focus)
16012  }
16013  else
16014  {
16015  TrainController->StopTTClockMessage(5, "Session file failed to open - reason not known, session unable to be saved.");
16016  }
16018  Screen->Cursor = TCursor(-2); // Arrow
16019  Utilities->CallLogPop(1141);
16020  }
16021  catch(const Exception &e)
16022  {
16023  ErrorLog(40, e.Message);
16024  }
16025 }
16026 
16027 // ---------------------------------------------------------------------------
16028 
16029 void TInterface::LoadSession(int Caller)
16030  // always loads in 'Paused' or 'PreStart' mode
16031 {
16032 // remember to load the timetable clock
16033 // no routes in build
16034 // prob need to set 'OperMode' then 'Paused', ensure have all info needed for these
16035 // set buttons enabled to correspond to flags on reloading. If no PrefDirs then disable all route buttons
16036 // set RlyFile true
16037  try
16038  {
16039  TrainController->LogEvent("LoadSession");
16040  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadSession");
16041  if(!ClearEverything(4))
16042  {
16043  Utilities->CallLogPop(1145);
16044  return;
16045  }
16046  LoadSessionDialog->Filter = "Session file (*.ssn)|*.ssn";
16047  if(LoadSessionDialog->Execute())
16048  {
16049  if(LoadSessionDialog->InitialDir != TPath::GetDirectoryName(LoadSessionDialog->FileName))//new at v2.6.0 to retain a new directory
16050  {
16051  LoadSessionDialog->InitialDir = TPath::GetDirectoryName(LoadSessionDialog->FileName);
16052  }
16053  TrainController->LogEvent("LoadSession " + LoadSessionDialog->FileName);
16054  Screen->Cursor = TCursor(-11); // Hourglass;
16055  if(SessionFileIntegrityCheck(0, AnsiString(LoadSessionDialog->FileName).c_str()))
16056  // if(true)
16057  {
16058  std::ifstream SessionFile(AnsiString(LoadSessionDialog->FileName).c_str());
16059  if(!(SessionFile.fail()))
16060  {
16061  TrainController->AvHoursIntValue = 0; // initial value set at v2.4.0 in case not changed later
16062  TrainController->MTBFHours = 0; // initial value set at v2.4.0 in case not changed later
16063  AnsiString TempString = Utilities->LoadFileString(SessionFile);
16064 // "version + : ***Interface***" + at v2.2.0 ExcessLCDownMins (omitted earlier)
16065 
16066  int LastCharBeforeFloat = TempString.LastDelimiter('*'); // added at v2.2.0
16067  if((LastCharBeforeFloat == 0) || (LastCharBeforeFloat == TempString.Length()))
16068  // can't find it or no value for Excess LCDownMins, either way count as zero
16069  {
16071  }
16072  else
16073  {
16074  AnsiString FloatStr = TempString.SubString(LastCharBeforeFloat + 1, TempString.Length() - LastCharBeforeFloat);
16075  if(!Utilities->CheckStringDouble(FloatStr)) // returns false for empty string or invalid double
16076  {
16078  }
16079  else
16080  {
16081  TrainController->ExcessLCDownMins = FloatStr.ToDouble();
16082  }
16083  } // end of v2.2.0 * v2.4.0 additions
16084 
16085  LoadInterface(0, SessionFile);
16086  int TempDisplayOffsetH = Display->DisplayOffsetH; // stored as they are zeroed when track loaded
16087  int TempDisplayOffsetV = Display->DisplayOffsetV;
16088  int TempDisplayOffsetHHome = Display->DisplayOffsetHHome;
16089  int TempDisplayOffsetVHome = Display->DisplayOffsetVHome;
16090  bool GraphicsFollow = false;
16091  // load track elements
16092  TempString = Utilities->LoadFileString(SessionFile); // ***Track***"
16093  Track->LoadTrack(4, SessionFile, GraphicsFollow);
16094  // load text elements
16095  TempString = Utilities->LoadFileString(SessionFile); // ***Text***"
16096  TextHandler->LoadText(1, SessionFile);
16097  // load PrefDir elements
16098  TempString = Utilities->LoadFileString(SessionFile); // "***PrefDirs***"
16099  EveryPrefDir->LoadPrefDir(1, SessionFile);
16100  if(GraphicsFollow)
16101  {
16102  Track->LoadGraphics(1, SessionFile, CurDir + "\\" + USERGRAPHICS_DIR_NAME); // include path to Graphics folder);
16103  }
16105  {
16106  SessionFile.close();
16107  Screen->Cursor = TCursor(-2); // Arrow;
16108  ShowMessage("Corruption in preferred direction section of the session file, session can't be loaded");
16109  Utilities->CallLogPop(1438);
16110  return;
16111  }
16112  // load routes
16113  TempString = Utilities->LoadFileString(SessionFile); // "***Routes***"
16114  if(!AllRoutes->LoadRoutes(0, SessionFile))
16115  {
16116  SessionFile.close();
16117  Screen->Cursor = TCursor(-2); // Arrow;
16118  ShowMessage("Corruption in route section of the session file, session can't be loaded");
16119  Utilities->CallLogPop(1439);
16120  return;
16121  }
16122  // load LockedRoutes
16123  TempString = Utilities->LoadFileString(SessionFile); // "***Locked routes***"
16124  TrainController->LoadSessionLockedRoutes(0, SessionFile);
16125  // load ContinuationAutoSigEntries
16126  TempString = Utilities->LoadFileString(SessionFile); // "***ContinuationAutoSigEntries***"
16128  // load BarriersDownVector if present, but ensure backwards compatibility with earlier files
16129  TempString = Utilities->LoadFileString(SessionFile); // "***BarriersDownVector***" or "***Timetable***"
16130  if(TempString == "***BarriersDownVector***")
16131  {
16132  Track->LoadBarriersDownVector(0, SessionFile);
16133  TempString = Utilities->LoadFileString(SessionFile); // "***Timetable***"
16134  }
16135  // load timetable (marker "***Timetable***" already loaded)
16136  if(!(LoadTimetableFromSessionFile(0, SessionFile)))
16137  {
16138  SessionFile.close();
16139  Screen->Cursor = TCursor(-2); // Arrow;
16140  ShowMessage("Unable to load timetable section of the session file, session can't be loaded");
16141  Utilities->CallLogPop(1151);
16142  return;
16143  }
16144  // TimetableTitle should be loaded at this stage - check
16145  if(TimetableTitle == "")
16146  {
16147  SessionFile.close();
16148  Screen->Cursor = TCursor(-2); // Arrow;
16149  throw Exception("TimetableTitle null in LoadSession");
16150  }
16151  // load timetable clock
16152  TempString = Utilities->LoadFileString(SessionFile); // ***TimetableClock***
16153  TrainController->RestartTime = TDateTime(Utilities->LoadFileDouble(SessionFile)); // ClockTime set in RestartSessionOperMode;
16154  // load trains
16155  TempString = Utilities->LoadFileString(SessionFile); // ***Trains***
16156  TrainController->LoadSessionTrains(0, SessionFile);
16157  // load performance file + populate the performance log
16158  TempString = Utilities->LoadFileString(SessionFile); // ***Performance file***
16159  // first reset the performance file name and open it before reloading it
16160  PerformanceFileName = TDateTime::CurrentDateTime().FormatString("dd-mm-yyyy hh.nn.ss");
16161  // avoid characters in filename:= / \ : * ? " < > |
16162  PerformanceFileName = CurDir + "\\" + PERFLOG_DIR_NAME + "\\Log " + PerformanceFileName + "; " + RailwayTitle + "; " +
16163  TimetableTitle + ".txt";
16164  Utilities->PerformanceFile.open(PerformanceFileName.c_str(), std::ios_base::out);
16165  if(Utilities->PerformanceFile.fail())
16166  {
16167  ShowMessage("Performance logfile failed to open, logs won't be saved. Ensure that there is a folder named " + PERFLOG_DIR_NAME +
16168  " in the folder where the 'Railway.exe' program file resides");
16169  }
16170  // now reload the performance file
16171  LoadPerformanceFile(0, SessionFile);
16172  // addition at v2.4.0
16173  char TempChar;
16174  SessionFile.get(TempChar);
16175  while(!SessionFile.eof() && ((TempChar == '\n') || (TempChar == '\0'))) // when emerge from here either have eof or '*'
16176  {
16177  SessionFile.get(TempChar);
16178  }
16179  if(SessionFile.eof()) // end of file
16180  {
16183  SessionFile.close(); // no TrainController->AvHoursIntValue & no failed trains
16184  }
16185  else
16186  {
16187  AnsiString DummyStr = Utilities->LoadFileString(SessionFile); // "**Additions after v2.3.1***" discarded (first '*' loaded earlier)
16188  TrainController->AvHoursIntValue = Utilities->LoadFileInt(SessionFile); // TrainController->AvHoursIntValue added at v2.4.0
16189  TrainController->NumFailures = Utilities->LoadFileInt(SessionFile); // number of train failures
16190  TrainController->MTBFHours = TrainController->AvHoursIntValue; // TTClockSpeed set to 1 in RestartSessionMode so no need to include here
16191  // now load any failed trains along with their OriginalPowerAtRail values
16192  DummyStr = Utilities->LoadFileString(SessionFile); // discard "***Failed Trains***"
16193  int ID = Utilities->LoadFileInt(SessionFile); // train ID or -1 for no more failed trains
16194  double PowerDouble;
16195  while(ID != -1)
16196  {
16197  PowerDouble = Utilities->LoadFileDouble(SessionFile); // ok TrainVector loaded at this stage (loaded in LoadSessionTrains)
16200  ID = Utilities->LoadFileInt(SessionFile);
16201  }
16202  SessionFile.close();
16203  }
16204  // deal with other settings
16205  Display->DisplayOffsetH = TempDisplayOffsetH; // reset to saved values
16206  Display->DisplayOffsetV = TempDisplayOffsetV;
16207  Display->DisplayOffsetHHome = TempDisplayOffsetHHome;
16208  Display->DisplayOffsetVHome = TempDisplayOffsetVHome;
16209  // now set attributes to 1 for all LCs with barriers down
16210  for(unsigned int x = 0; x < Track->BarriersDownVector.size(); x++)
16211  {
16213  }
16214  Track->ChangingLCVector.clear();
16215  Track->CalcHLocMinEtc(10);
16217  SetLevel1Mode(27);
16218  if(Level2OperMode == PreStart)
16219  // this section added at v1.3.2 as otherwise only in MainScreenMouseDown2, and if load a session without clicking mouse on screen
16220  { // then delay unspecified though seems to be 0
16221  PointsFlashDuration = 0.0;
16224  }
16225  else
16226  {
16230  }
16231  RlyFile = true;
16232  SetCaption(3);
16234  }
16235  }
16236  else
16237  {
16238  ShowMessage("Session file integrity check failed, unable to load session.");
16239  }
16240  Screen->Cursor = TCursor(-2); // Arrow;
16241  }
16242  Utilities->CallLogPop(1146);
16243  }
16244  catch(const Exception &e)
16245  {
16246  if((e.Message.Pos("esource") > 0) || (e.Message.Pos("arameter") > 0)) // 'Resource or Parameter, avoid capitals as may be OS dependent
16247  {
16248  Screen->Cursor = TCursor(-2); // Arrow;
16249  OutputLog1->Caption = "";
16250  OutputLog2->Caption = "";
16251  OutputLog3->Caption = "";
16252  OutputLog4->Caption = "";
16253  OutputLog5->Caption = "";
16254  OutputLog6->Caption = "";
16255  OutputLog7->Caption = "";
16256  OutputLog8->Caption = "";
16257  OutputLog9->Caption = "";
16258  OutputLog10->Caption = "";
16259  UnicodeString MessageStr =
16260  "Insufficient memory available to load the file, and partial load likely to be corrupt. Application will terminate. Try loading the session as the first action after reloading the program.";
16261 // UnicodeString MessageStr = "Last train loaded = " + UnicodeString(TrainController->LastTrainLoaded); //for debugging session train loading for many trains
16262  Application->MessageBox(MessageStr.c_str(), L"Out of memory", MB_OK | MB_ICONERROR);
16263  Application->Terminate();
16264  }
16265  else
16266  {
16267  ErrorLog(41, e.Message);
16268  }
16269  }
16270 }
16271 
16272 // ---------------------------------------------------------------------------
16273 
16274 void TInterface::SaveInterface(int Caller, std::ofstream &SessionFile)
16275 {
16276  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveInterface");
16277  if(Level2OperMode == PreStart)
16278  Utilities->SaveFileString(SessionFile, AnsiString("PreStart"));
16279  else
16280  Utilities->SaveFileString(SessionFile, AnsiString("NotPreStart")); // covers both Paused & Operating
16281  Utilities->SaveFileString(SessionFile, RailwayTitle);
16282  Utilities->SaveFileString(SessionFile, TimetableTitle);
16283  Utilities->SaveFileBool(SessionFile, PreferredRoute);
16284  Utilities->SaveFileBool(SessionFile, ConsecSignalsRoute);
16285  Utilities->SaveFileBool(SessionFile, AutoSigsFlag);
16286  Utilities->SaveFileInt(SessionFile, Display->DisplayOffsetH);
16287  Utilities->SaveFileInt(SessionFile, Display->DisplayOffsetV);
16292  Utilities->SaveFileString(SessionFile, OutputLog1->Caption);
16293  Utilities->SaveFileString(SessionFile, OutputLog2->Caption);
16294  Utilities->SaveFileString(SessionFile, OutputLog3->Caption);
16295  Utilities->SaveFileString(SessionFile, OutputLog4->Caption);
16296  Utilities->SaveFileString(SessionFile, OutputLog5->Caption);
16297  Utilities->SaveFileString(SessionFile, OutputLog6->Caption);
16298  Utilities->SaveFileString(SessionFile, OutputLog7->Caption);
16299  Utilities->SaveFileString(SessionFile, OutputLog8->Caption);
16300  Utilities->SaveFileString(SessionFile, OutputLog9->Caption);
16301  Utilities->SaveFileString(SessionFile, OutputLog10->Caption);
16302 
16324  // ExcessLCDownMins saved after ***Interface*** at v2.2.0 (omitted in error earlier)
16325  Utilities->CallLogPop(1211);
16326 }
16327 
16328 // ---------------------------------------------------------------------------
16329 void TInterface::LoadInterface(int Caller, std::ifstream &SessionFile)
16330 {
16331  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadInterface");
16332  AnsiString OpMode = Utilities->LoadFileString(SessionFile);
16333 
16334  if(OpMode == "PreStart")
16336  else
16338  RailwayTitle = Utilities->LoadFileString(SessionFile);
16339  SavedFileName = CurDir + "\\" + RAILWAY_DIR_NAME + "\\" + RailwayTitle + ".rly";
16340 
16341  TimetableTitle = Utilities->LoadFileString(SessionFile);
16342  PreferredRoute = Utilities->LoadFileBool(SessionFile);
16343  ConsecSignalsRoute = Utilities->LoadFileBool(SessionFile);
16344  AutoSigsFlag = Utilities->LoadFileBool(SessionFile);
16345  Display->DisplayOffsetH = Utilities->LoadFileInt(SessionFile);
16346  Display->DisplayOffsetV = Utilities->LoadFileInt(SessionFile);
16351  OutputLog1->Caption = Utilities->LoadFileString(SessionFile);
16352  OutputLog2->Caption = Utilities->LoadFileString(SessionFile);
16353  OutputLog3->Caption = Utilities->LoadFileString(SessionFile);
16354  OutputLog4->Caption = Utilities->LoadFileString(SessionFile);
16355  OutputLog5->Caption = Utilities->LoadFileString(SessionFile);
16356  OutputLog6->Caption = Utilities->LoadFileString(SessionFile);
16357  OutputLog7->Caption = Utilities->LoadFileString(SessionFile);
16358  OutputLog8->Caption = Utilities->LoadFileString(SessionFile);
16359  OutputLog9->Caption = Utilities->LoadFileString(SessionFile);
16360  OutputLog10->Caption = Utilities->LoadFileString(SessionFile);
16361 
16369  TrainController->LateDeps = Utilities->LoadFileInt(SessionFile);
16383  Utilities->CallLogPop(1212);
16384 }
16385 
16386 // ---------------------------------------------------------------------------
16387 
16388 bool TInterface::CheckInterface(int Caller, std::ifstream &SessionFile)
16389 {
16390  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",CheckInterface");
16391 
16392  AnsiString OpMode = "";
16393 
16394  if(!Utilities->CheckAndReadFileString(SessionFile, OpMode))
16395  {
16396  Utilities->CallLogPop(1767);
16397  return false;
16398  }
16399  else if((OpMode != "PreStart") && (OpMode != "NotPreStart"))
16400  {
16401  Utilities->CallLogPop(1768);
16402  return false;
16403  }
16404  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile)) // RailwayTitle
16405  {
16406  Utilities->CallLogPop(1213);
16407  return false;
16408  }
16409  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile)) // TimetableTitle
16410  {
16411  Utilities->CallLogPop(1214);
16412  return false;
16413  }
16414  if(!Utilities->CheckFileBool(SessionFile))
16415  {
16416  Utilities->CallLogPop(1216);
16417  return false;
16418  }
16419  if(!Utilities->CheckFileBool(SessionFile))
16420  {
16421  Utilities->CallLogPop(1217);
16422  return false;
16423  }
16424  if(!Utilities->CheckFileBool(SessionFile))
16425  {
16426  Utilities->CallLogPop(1218);
16427  return false;
16428  }
16429  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16430  {
16431  Utilities->CallLogPop(1409);
16432  return false;
16433  }
16434  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16435  {
16436  Utilities->CallLogPop(1486);
16437  return false;
16438  }
16439  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16440  {
16441  Utilities->CallLogPop(1487);
16442  return false;
16443  }
16444  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16445  {
16446  Utilities->CallLogPop(1488);
16447  return false;
16448  }
16449  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16450  {
16451  Utilities->CallLogPop(1489);
16452  return false;
16453  }
16454  if(!Utilities->CheckFileInt(SessionFile, -1000000, 1000000))
16455  {
16456  Utilities->CallLogPop(1528);
16457  return false;
16458  }
16459  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16460  {
16461  Utilities->CallLogPop(1725);
16462  return false;
16463  }
16464  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16465  {
16466  Utilities->CallLogPop(1726);
16467  return false;
16468  }
16469  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16470  {
16471  Utilities->CallLogPop(1727);
16472  return false;
16473  }
16474  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16475  {
16476  Utilities->CallLogPop(1728);
16477  return false;
16478  }
16479  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16480  {
16481  Utilities->CallLogPop(1730);
16482  return false;
16483  }
16484  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16485  {
16486  Utilities->CallLogPop(1731);
16487  return false;
16488  }
16489  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16490  {
16491  Utilities->CallLogPop(1732);
16492  return false;
16493  }
16494  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16495  {
16496  Utilities->CallLogPop(1733);
16497  return false;
16498  }
16499  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16500  {
16501  Utilities->CallLogPop(1734);
16502  return false;
16503  }
16504  if(!Utilities->CheckFileStringZeroDelimiter(SessionFile))
16505  {
16506  Utilities->CallLogPop(1789);
16507  return false;
16508  }
16509 
16510  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16511  {
16512  Utilities->CallLogPop(1737);
16513  return false;
16514  }
16515  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16516  {
16517  Utilities->CallLogPop(1738);
16518  return false;
16519  }
16520  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16521  {
16522  Utilities->CallLogPop(1739);
16523  return false;
16524  }
16525  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16526  {
16527  Utilities->CallLogPop(1740);
16528  return false;
16529  }
16530  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16531  {
16532  Utilities->CallLogPop(1741);
16533  return false;
16534  }
16535  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16536  {
16537  Utilities->CallLogPop(1742);
16538  return false;
16539  }
16540  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16541  {
16542  Utilities->CallLogPop(1743);
16543  return false;
16544  }
16545  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16546  {
16547  Utilities->CallLogPop(1744);
16548  return false;
16549  }
16550  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16551  {
16552  Utilities->CallLogPop(1745);
16553  return false;
16554  }
16555  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16556  {
16557  Utilities->CallLogPop(1746);
16558  return false;
16559  }
16560  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16561  {
16562  Utilities->CallLogPop(1747);
16563  return false;
16564  }
16565  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16566  {
16567  Utilities->CallLogPop(1748);
16568  return false;
16569  }
16570  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16571  {
16572  Utilities->CallLogPop(1749);
16573  return false;
16574  }
16575  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16576  {
16577  Utilities->CallLogPop(1750);
16578  return false;
16579  }
16580  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16581  {
16582  Utilities->CallLogPop(1751);
16583  return false;
16584  }
16585  if(!Utilities->CheckFileInt(SessionFile, 0, 1000000))
16586  {
16587  Utilities->CallLogPop(1752);
16588  return false;
16589  }
16590 
16591  if(!Utilities->CheckFileDouble(SessionFile))
16592  {
16593  Utilities->CallLogPop(1753);
16594  return false;
16595  }
16596  if(!Utilities->CheckFileDouble(SessionFile))
16597  {
16598  Utilities->CallLogPop(1754);
16599  return false;
16600  }
16601  if(!Utilities->CheckFileDouble(SessionFile))
16602  {
16603  Utilities->CallLogPop(1755);
16604  return false;
16605  }
16606  if(!Utilities->CheckFileDouble(SessionFile))
16607  {
16608  Utilities->CallLogPop(1756);
16609  return false;
16610  }
16611  if(!Utilities->CheckFileDouble(SessionFile))
16612  {
16613  Utilities->CallLogPop(1757);
16614  return false;
16615  }
16616  Utilities->CallLogPop(1219);
16617  return true;
16618 }
16619 
16620 // ---------------------------------------------------------------------------
16621 
16622 bool TInterface::SaveTimetableToSessionFile(int Caller, std::ofstream &SessionFile, AnsiString SessionFileStr)
16623 {
16624  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveTimetableToSessionFile," + SessionFileStr);
16625  if(!FileExists(TempTTFileName))
16626  {
16627  Utilities->CallLogPop(1862);
16628  return false;
16629  }
16630 
16631  SessionFile.close(); // close & re-open in append & binary mode so LF characters copy as LFs & not CRLFs
16632  SessionFile.open(SessionFileStr.c_str(), std::ios_base::app | std::ios_base::binary); // file pointer set to end
16633 
16634  int Handle = FileOpen(TempTTFileName, fmOpenRead);
16635  int Count = 0;
16636 
16637  while(Handle < 0) // this type of file use failed when used in SaveTempTimetableFile when used to resave timetable.tmp from
16638  // temp .ttb file, but changed that to avoid so many rapid file actions in quick succession & been OK since
16639  // then, but nevertheless have 10 retries before giving message to be on safe side
16640  {
16641  Handle = FileOpen(TempTTFileName, fmOpenRead);
16642  Count++;
16643  Delay(1, 50); // 50mSec delay between tries
16644  if(Count > 10)
16645  {
16646  ShowMessage("Failed to open temporary timetable file. Unable to save the session");
16647  Utilities->CallLogPop(1221);
16648  return false;
16649  }
16650  }
16651 
16652  char *Buffer = new char[10000];
16653  int BytesRead;
16654 
16655  while(true)
16656  {
16657  BytesRead = FileRead(Handle, Buffer, 10000);
16658  SessionFile.write(Buffer, BytesRead);
16659  if(BytesRead < 10000)
16660  break;
16661  }
16662  delete Buffer;
16663  FileClose(Handle);
16664 
16665  SessionFile.close(); // close & re-open in append & text out mode as before so can write text
16666  SessionFile.open(SessionFileStr.c_str(), std::ios_base::app | std::ios_base::out); // file pointer set to end
16667 
16668  Utilities->SaveFileString(SessionFile, "***End***"); // marker for end of timetable
16669 // now need to save the TrainOperatingData so can be loaded back into the timetable as is
16670  Utilities->SaveFileInt(SessionFile, TrainController->TrainDataVector.size());
16671  for(unsigned int x = 0; x < TrainController->TrainDataVector.size(); x++)
16672  {
16673  Utilities->SaveFileInt(SessionFile, TrainController->TrainDataVector.at(x).TrainOperatingDataVector.size());
16674  for(unsigned int y = 0; y < TrainController->TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
16675  {
16676  Utilities->SaveFileInt(SessionFile, TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).TrainID);
16677  Utilities->SaveFileInt(SessionFile, (short)(TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).EventReported));
16678  Utilities->SaveFileInt(SessionFile, (short)(TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).RunningEntry));
16679  }
16680  }
16681  Utilities->CallLogPop(1220);
16682  return true;
16683 }
16684 
16685 // ---------------------------------------------------------------------------
16686 
16687 bool TInterface::SaveTimetableToErrorFile(int Caller, std::ofstream &ErrorFile, AnsiString ErrorFileStr, AnsiString TimetableFileName)
16688 {
16689  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveTimetableToErrorFile," + ErrorFileStr + "," + TimetableFileName);
16690  if(!FileExists(TimetableFileName))
16691  {
16692  Utilities->CallLogPop(1863);
16693  return false;
16694  }
16695 
16696  ErrorFile.close(); // close & re-open in append & binary mode so LF characters copy as LFs & not CRLFs
16697  ErrorFile.open(ErrorFileStr.c_str(), std::ios_base::app | std::ios_base::binary); // file pointer set to end
16698 
16699  int Handle = FileOpen(TimetableFileName, fmOpenRead);
16700  int Count = 0;
16701 
16702  while(Handle < 0) // this type of file use failed when used in SaveTempTimetableFile when used to resave timetable.tmp from
16703  // temp .ttb file, but changed that to avoid so many rapid file actions in quick succession & been OK since
16704  // then, but nevertheless have 10 retries before giving message to be on safe side
16705  {
16706  Handle = FileOpen(TimetableFileName, fmOpenRead);
16707  Count++;
16708  Delay(5, 50); // 50mSec delay between tries
16709  if(Count > 10)
16710  {
16711  Utilities->CallLogPop(1835);
16712  return false;
16713  }
16714  }
16715 
16716  char *Buffer = new char[10000];
16717  int BytesRead;
16718 
16719  while(true)
16720  {
16721  BytesRead = FileRead(Handle, Buffer, 10000);
16722  ErrorFile.write(Buffer, BytesRead);
16723  if(BytesRead < 10000)
16724  break;
16725  }
16726  delete Buffer;
16727  FileClose(Handle);
16728 
16729  ErrorFile.close(); // close & re-open in append & text out mode as before so can write text
16730  ErrorFile.open(ErrorFileStr.c_str(), std::ios_base::app | std::ios_base::out); // file pointer set to end
16731 
16732  Utilities->SaveFileString(ErrorFile, "***End of timetable***"); // marker for end of timetable
16733  Utilities->CallLogPop(1836);
16734  return true;
16735 }
16736 
16737 // ---------------------------------------------------------------------------
16738 
16739 bool TInterface::LoadTimetableFromSessionFile(int Caller, std::ifstream &SessionFile)
16740  // the .ttb section is delimited by "***End***"
16741  // create the temporary timetable file in the working folder exactly like the original
16742 {
16743  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadTimetableFromSessionFile");
16744  // reset all message flags, stops them being given twice (shouldn't be needed here but add for safety) //new at v2.4.0
16745  TrainController->SSHigh = false;
16746  TrainController->MRSHigh = false;
16747  TrainController->MRSLow = false;
16748  TrainController->MassHigh = false;
16749  TrainController->BFHigh = false;
16750  TrainController->BFLow = false;
16751  TrainController->PwrHigh = false;
16752  TrainController->SigSHigh = false;
16753  TrainController->SigSLow = false;
16754  if((TempTTFileName != "") && FileExists(TempTTFileName))
16755  {
16756  DeleteFile(TempTTFileName);
16757  }
16758  int TempTTFileNumber = 0;
16759 
16760  while(FileExists(CurDir + "\\TmpTT" + AnsiString(TempTTFileNumber) + ".tmp"))
16761  {
16762  TempTTFileNumber++;
16763  }
16764  TempTTFileName = CurDir + "\\TmpTT" + AnsiString(TempTTFileNumber) + ".tmp";
16765 
16766  std::ofstream TTBFile(TempTTFileName.c_str()); // use text mode as SessionFile is in text mode, so CRLFs read as LFs, and LFs write as CRLFs.
16767  int Count;
16768  char Zero = '\0';
16769 
16770  if(!TTBFile.fail())
16771  {
16772  char *Buffer = new char[10000]; // can't use LoadFileString as that expects a '\0' delimiter
16773  char TempChar = (char)(SessionFile.peek()); // have a look at the next character, if it's '\n'
16774  if(TempChar == '\n')
16775  SessionFile.get(TempChar); // then get rid of it, else leave it in as part of the first line
16776  if(!SessionFile.getline(Buffer, 10000, '\0'))
16777  {
16778  TTBFile.close();
16779  DeleteFile(TempTTFileName);
16780  delete Buffer;
16781  Utilities->CallLogPop(1222);
16782  return false;
16783  }
16784  Count = 0;
16785  for(int x = 0; x < 10000; x++)
16786  {
16787  if(Buffer[x] != '\0')
16788  Count++;
16789  else
16790  break;
16791  }
16792  while(AnsiString(Buffer) != "***End***")
16793  {
16794  TTBFile.write(Buffer, Count);
16795  TTBFile.write(&Zero, 1);
16796 // TTBFile.write(&NewLine, 1);
16797  if(!SessionFile.getline(Buffer, 10000, '\0'))
16798  {
16799  TTBFile.close();
16800  DeleteFile(TempTTFileName);
16801  delete Buffer;
16802  Utilities->CallLogPop(1223);
16803  return false;
16804  }
16805  Count = 0;
16806  for(int x = 0; x < 10000; x++)
16807  {
16808  if(Buffer[x] != '\0')
16809  Count++;
16810  else
16811  break;
16812  }
16813  }
16814  TTBFile.close();
16815  delete Buffer;
16816 // SaveTempTimetableFile(1, TTBFileName); no need, already has required name
16817 // now create the internal timetable from the .tmp file
16818  bool GiveMessagesFalse = false;
16819  bool CheckLocationsExistInRailwayTrue = true;
16820  if(TrainController->TimetableIntegrityCheck(1, TempTTFileName.c_str(), GiveMessagesFalse, CheckLocationsExistInRailwayTrue))
16821  {
16822  std::ifstream TTBLFile(TempTTFileName.c_str(), std::ios_base::binary);
16823  if(TTBLFile.is_open())
16824  {
16825  bool SessionFileTrue = true;
16826  if(!(BuildTrainDataVectorForLoadFile(1, TTBLFile, GiveMessagesFalse, CheckLocationsExistInRailwayTrue, SessionFileTrue)))
16827  {
16828  TTBLFile.close();
16829  DeleteFile(TempTTFileName);
16830  Utilities->CallLogPop(1224);
16831  return false;
16832  }
16833  }
16834  else
16835  {
16836  DeleteFile(TempTTFileName);
16837  Utilities->CallLogPop(1225);
16838  return false;
16839  }
16840  } // if(FileIntegrityCheck(TTBFileName.c_str()))
16841  else
16842  {
16843  DeleteFile(TempTTFileName);
16844  Utilities->CallLogPop(1226);
16845  return false;
16846  }
16847 // DeleteFile(TempTTFileName); no, need to save it for later session saves
16848 
16849  // now need to load the TrainOperatingData so can be loaded back into the timetable
16850  int NumberOfTrainEntries = Utilities->LoadFileInt(SessionFile);
16851  if(NumberOfTrainEntries != (int)(TrainController->TrainDataVector.size()))
16852  {
16853  Utilities->CallLogPop(1811);
16854  return false;
16855  }
16856  for(int x = 0; x < NumberOfTrainEntries; x++)
16857  {
16858  int NumberOfTrains = Utilities->LoadFileInt(SessionFile);
16859  if(NumberOfTrains != (int)(TrainController->TrainDataVector.at(x).TrainOperatingDataVector.size()))
16860  {
16861  Utilities->CallLogPop(1812);
16862  return false;
16863  }
16864  for(int y = 0; y < NumberOfTrains; y++)
16865  {
16866  TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).TrainID = Utilities->LoadFileInt(SessionFile);
16867  TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).EventReported = (TActionEventType)(Utilities->LoadFileInt(SessionFile));
16868  TrainController->TrainDataVector.at(x).TrainOperatingDataVector.at(y).RunningEntry = (TRunningEntry)(Utilities->LoadFileInt(SessionFile));
16869  }
16870  }
16871  Utilities->CallLogPop(1227);
16872  return true;
16873  }
16874  else
16875  {
16876  Utilities->CallLogPop(1228);
16877  return false;
16878  }
16879 }
16880 
16881 // ---------------------------------------------------------------------------
16882 
16883 bool TInterface::CheckTimetableFromSessionFile(int Caller, std::ifstream &SessionFile)
16884  // the .ttb section is delimited by '\0' followed by "***End***" & has been saved in binary mode, i.e. no '\0'
16885  // string delimiters between entries, this check function just checks the (non-zero terminated) string entries in the file without
16886  // trying to build a timetable - that's done during load
16887 {
16888  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",CheckTimetableFromSessionFile");
16889  AnsiString OutString;
16890 
16891  if(!Utilities->CheckAndReadFileString(SessionFile, OutString))
16892  {
16893  Utilities->CallLogPop(1229);
16894  return false;
16895  }
16896  while(OutString != "***End***")
16897  {
16898  if(!Utilities->CheckAndReadFileString(SessionFile, OutString))
16899  {
16900  Utilities->CallLogPop(1230);
16901  return false;
16902  }
16903  }
16904 // now need to check the TrainOperatingData, which was saved in text mode
16905  if(SessionFile.fail())
16906  {
16907  Utilities->CallLogPop(1231);
16908  return false;
16909  }
16910  int NumberOfTrainEntries;
16911 
16912  if(!Utilities->CheckAndReadFileInt(SessionFile, 0, 10000, NumberOfTrainEntries))
16913  {
16914  Utilities->CallLogPop(1232);
16915  return false;
16916  }
16917  for(int x = 0; x < NumberOfTrainEntries; x++)
16918  {
16919  int NumberOfTrains;
16920  if(!Utilities->CheckAndReadFileInt(SessionFile, 0, 10000, NumberOfTrains))
16921  {
16922  Utilities->CallLogPop(1233);
16923  return false;
16924  }
16925  for(int y = 0; y < NumberOfTrains; y++)
16926  {
16927  if(!Utilities->CheckFileInt(SessionFile, -1, 1000000)) // TrainID
16928  {
16929  Utilities->CallLogPop(1234);
16930  return false;
16931  }
16932  if(!Utilities->CheckFileInt(SessionFile, 0, 30)) // EventReported
16933  {
16934  Utilities->CallLogPop(1235);
16935  return false;
16936  }
16937  if(!Utilities->CheckFileInt(SessionFile, 0, 2)) // RunningEntry
16938  {
16939  Utilities->CallLogPop(1236);
16940  return false;
16941  }
16942  }
16943  }
16944  Utilities->CallLogPop(1237);
16945  return true;
16946 }
16947 
16948 // ---------------------------------------------------------------------------
16949 
16950 bool TInterface::BuildTrainDataVectorForLoadFile(int Caller, std::ifstream &TTBLFile, bool GiveMessages, bool CheckLocationsExistInRailway, bool SessionFile)
16951 {
16952  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",BuildTrainDataVectorForLoadFile," + AnsiString((short)GiveMessages));
16953  TrainController->TrainDataVector.clear(); // get rid of any earlier timetable
16954  bool EndOfFile = false;
16955  int Count = 0;
16956  char *TrainTimetableString = new char[10000]; // enough for ~ 200 stations at 50 chars/station, should be adequate!
16957 
16958  while(!EndOfFile)
16959  {
16960  TTBLFile.getline(TrainTimetableString, 10000, '\0');
16961  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // stores a null in 1st position if doesn't load any characters
16962  { // may still have eof even if read a line (no CRLF at end), and
16963  // if so need to process it
16964  EndOfFile = true;
16965  break;
16966  }
16967  AnsiString OneLine(TrainTimetableString);
16968  bool FinalCallTrue = true;
16969  while((Count == 0) && !TrainController->ProcessOneTimetableLine(3, Count, OneLine, EndOfFile, FinalCallTrue, GiveMessages,
16970  CheckLocationsExistInRailway)) // get rid of lines before the start time
16971  {
16972  TTBLFile.getline(TrainTimetableString, 10000, '\0');
16973  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // see above
16974  {
16975  TTBLFile.close();
16976  throw Exception("Timetable FinalCall error - no start time on own line, Count = 0");
16977  }
16978  OneLine = AnsiString(TrainTimetableString);
16979  }
16980  // here when have accepted the start time
16981  if(Count == 0)
16982  {
16983  Count++; // increment past the start time
16984  TTBLFile.getline(TrainTimetableString, 10000, '\0'); // get next line after start time
16985  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // see above
16986  {
16987  EndOfFile = true;
16988  OneLine = "";
16989  }
16990  else
16991  OneLine = AnsiString(TrainTimetableString);
16992  }
16993  if(!TrainController->ProcessOneTimetableLine(4, Count, OneLine, EndOfFile, FinalCallTrue, GiveMessages, CheckLocationsExistInRailway))
16994  {
16995  TTBLFile.close();
16996  throw Exception("Timetable FinalCall error in processing one timetable line, Count = " + AnsiString(Count));
16997  }
16998  if(EndOfFile && (Count < 2)) // Timetable must contain at least two relevant lines, one for start time and at least one train
16999  {
17000  TTBLFile.close();
17001  throw Exception("Timetable FinalCall error - too few or no relevant entries, Count = " + AnsiString(Count));
17002  }
17003  Count++;
17004  }
17005  TTBLFile.close();
17006  delete TrainTimetableString;
17007 // here when first pass actions completed successfully
17008  if(!TrainController->SecondPassActions(0, GiveMessages)) // Check for matching join/split HeadCodes, check increasing times & matching split/join
17009  // times, complete arrival & departure times for each TT line, check & complete train info for each type of start,
17010  // messages given in function if errors & vector cleared
17011  {
17012  if(GiveMessages)
17013  ShowMessage("Timetable secondary integrity check failed - unable to load");
17014  Utilities->CallLogPop(1238);
17015  return false;
17016  }
17017  else
17018  {
17019 // TimetableLoaded = true;
17020  if(!SessionFile) // new timetable being loaded so need new TimetableTitle, if SessionFile true then already have it from LoadInterface
17021  {
17022  for(int x = TimetableDialog->FileName.Length(); x > 0; x--)
17023  {
17024  if(TimetableDialog->FileName[x] == '\\')
17025  {
17026  TimetableTitle = TimetableDialog->FileName.SubString(x + 1, TimetableDialog->FileName.Length() - x - 4);
17027  SetCaption(4);
17028  break;
17029  }
17030  }
17031  }
17032 // if(GiveMessages) //only set BaseMode if have manually loaded a timetable changed for the below in v2.4.0
17033  if(!SessionFile) // only set BaseMode if have manually loaded a timetable, i.e SessionFile is false
17034  {
17035  Level1Mode = BaseMode;
17036  SetLevel1Mode(28);
17037  }
17038  }
17039  Utilities->CallLogPop(1239);
17040  return true;
17041 }
17042 
17043 // ---------------------------------------------------------------------------
17044 
17045 bool TInterface::BuildTrainDataVectorForValidateFile(int Caller, std::ifstream &TTBLFile, bool GiveMessages, bool CheckLocationsExistInRailway)
17046 {
17047  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",BuildTrainDataVectorForValidateFile," + AnsiString((short)GiveMessages));
17048  TrainController->TrainDataVector.clear(); // get rid of any earlier timetable
17049  bool EndOfFile = false;
17050  int Count = 0;
17051  char *TrainTimetableString = new char[10000]; // enough for ~ 200 stations at 50 chars/station, should be adequate!
17052 
17053  while(!EndOfFile)
17054  {
17055  TTBLFile.getline(TrainTimetableString, 10000, '\0');
17056  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // stores a null in 1st position if doesn't load any characters
17057  { // may still have eof even if read a line (no CRLF at end), and
17058  // if so need to process it
17059  EndOfFile = true;
17060  break;
17061  }
17062  AnsiString OneLine(TrainTimetableString);
17063  bool FinalCallTrue = true;
17064  while((Count == 0) && !TrainController->ProcessOneTimetableLine(0, Count, OneLine, EndOfFile, FinalCallTrue, GiveMessages,
17065  CheckLocationsExistInRailway)) // get rid of lines before the start time
17066  {
17067  TTBLFile.getline(TrainTimetableString, 10000, '\0');
17068  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // see above
17069  {
17070  TTBLFile.close();
17071  throw Exception("Timetable FinalCall error - no start time on own line, Count = 0");
17072  }
17073  OneLine = AnsiString(TrainTimetableString);
17074  }
17075  // here when have accepted the start time
17076  if(Count == 0)
17077  {
17078  Count++; // increment past the start time
17079  TTBLFile.getline(TrainTimetableString, 10000, '\0'); // get next line after start time
17080  if(TTBLFile.eof() && (TrainTimetableString[0] == '\0')) // see above
17081  {
17082  EndOfFile = true;
17083  OneLine = "";
17084  }
17085  else
17086  OneLine = AnsiString(TrainTimetableString);
17087  }
17088  if(!TrainController->ProcessOneTimetableLine(1, Count, OneLine, EndOfFile, FinalCallTrue, GiveMessages, CheckLocationsExistInRailway))
17089  {
17090  TTBLFile.close();
17091  throw Exception("Timetable FinalCall error in processing one timetable line, Count = " + AnsiString(Count));
17092  }
17093  if(EndOfFile && (Count < 2)) // Timetable must contain at least two relevant lines, one for start time and at least one train
17094  {
17095  TTBLFile.close();
17096  throw Exception("Timetable FinalCall error - too few or no relevant entries, Count = " + AnsiString(Count));
17097  }
17098  Count++;
17099  }
17100  TTBLFile.close();
17101  delete TrainTimetableString;
17102 // here when first pass actions completed successfully
17103  if(!TrainController->SecondPassActions(1, GiveMessages)) // Check for matching join/split HeadCodes, check increasing times & matching split/join
17104  // times, complete arrival & departure times for each TT line, check & complete train info for each type of start,
17105  // messages given in function if errors & vector cleared
17106  {
17107 // if(GiveMessages) ShowMessage("Timetable secondary integrity check failed");
17108 // above dropped in v2.4.0 as all called functions give own messages
17109  Utilities->CallLogPop(1665);
17110  return false;
17111  }
17112  Utilities->CallLogPop(1666);
17113  return true;
17114 }
17115 
17116 // ---------------------------------------------------------------------------
17117 
17118 bool TInterface::SessionFileIntegrityCheck(int Caller, AnsiString FileName)
17119 /* Here need to check as far as timetable, then go back and load the track, because the timetable compilation check
17120  relies on the track vector and map being in place. Won't affect the later load because the vector and map are cleared
17121  before loading.
17122 
17123  Although this appears cumbersome, I initially used tellg() & seekg() to reposition the file pointer without having to do
17124  all this backtracking. However after many problems I eventually found that tellg() sometimes returns false values,
17125  which cause problems when reloaded using seekg(). This must be a compiler problem, though I could find no mention of it
17126  in the CBuilder4 issues list or on the web. The full write-up is at the end of this unit.
17127 
17128  Also, with hindsight, I wish I had just saved and reloaded the timetable vectors rather than the text of the timetable. That
17129  would probably have been easier. To change it now though would cause compatibility problems with sessions created by earlier versions.
17130 */
17131 {
17132  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SessionFileIntegrityCheck," + FileName);
17133  std::ifstream InFile(FileName.c_str());
17134 // first pass as far as timetable
17135  int NumberOfActiveElements;
17136  bool GraphicsFollow = false;
17137 
17138  if(InFile.is_open())
17139  {
17141  // expected to be "***Interface***" for original version or "Version + : ***Interface***" for later releases + ExcessLCDownMins added as float after v2.2.0
17142  {
17143  InFile.close();
17144  Utilities->CallLogPop(1240);
17145  return false;
17146  }
17147  if(!CheckInterface(0, InFile))
17148  {
17149  InFile.close();
17150  Utilities->CallLogPop(1241);
17151  return false;
17152  }
17153  // check track elements
17154  if(!Utilities->CheckAndCompareFileString(InFile, "***Track***"))
17155  {
17156  InFile.close();
17157  Utilities->CallLogPop(1242);
17158  return false;
17159  }
17160  if(!Track->CheckTrackElementsInFile(2, NumberOfActiveElements, GraphicsFollow, InFile))
17161  {
17162  InFile.close();
17163  Utilities->CallLogPop(1243);
17164  return false;
17165  }
17166  if(InFile.fail())
17167  {
17168  InFile.close();
17169  Utilities->CallLogPop(1244);
17170  return false;
17171  }
17172  // check text elements
17173  if(!Utilities->CheckAndCompareFileString(InFile, "***Text***"))
17174  {
17175  InFile.close();
17176  Utilities->CallLogPop(1245);
17177  return false;
17178  }
17179  if(!TextHandler->CheckTextElementsInFile(1, InFile))
17180  {
17181  InFile.close();
17182  Utilities->CallLogPop(1246);
17183  return false;
17184  }
17185  if(InFile.fail())
17186  {
17187  InFile.close();
17188  Utilities->CallLogPop(1247);
17189  return false;
17190  }
17191  // check PrefDir elements
17192  if(!Utilities->CheckAndCompareFileString(InFile, "***PrefDirs***"))
17193  {
17194  InFile.close();
17195  Utilities->CallLogPop(1248);
17196  return false;
17197  }
17198  if(!EveryPrefDir->CheckOnePrefDir(1, NumberOfActiveElements, InFile))
17199  {
17200  InFile.close();
17201  Utilities->CallLogPop(1249);
17202  return false;
17203  }
17204  if(InFile.fail())
17205  {
17206  InFile.close();
17207  Utilities->CallLogPop(1250);
17208  return false;
17209  }
17210  // check graphics
17211  if(GraphicsFollow)
17212  {
17213  if(!Track->CheckUserGraphics(1, InFile, CurDir + "\\" + USERGRAPHICS_DIR_NAME)) // include path to Graphics folder
17214  {
17215  InFile.close();
17216  Utilities->CallLogPop(2187);
17217  return false;
17218  }
17219  if(InFile.fail())
17220  {
17221  InFile.close();
17222  Utilities->CallLogPop(2188);
17223  return false;
17224  }
17225  }
17226  // check routes
17227  if(!Utilities->CheckAndCompareFileString(InFile, "***Routes***"))
17228  {
17229  InFile.close();
17230  Utilities->CallLogPop(1251);
17231  return false;
17232  }
17233  if(!AllRoutes->CheckRoutes(0, NumberOfActiveElements, InFile))
17234  {
17235  InFile.close();
17236  Utilities->CallLogPop(1252);
17237  return false;
17238  }
17239  if(InFile.fail())
17240  {
17241  InFile.close();
17242  Utilities->CallLogPop(1253);
17243  return false;
17244  }
17245  // check LockedRoutes
17246  if(!Utilities->CheckAndCompareFileString(InFile, "***Locked routes***"))
17247  {
17248  InFile.close();
17249  Utilities->CallLogPop(1254);
17250  return false;
17251  }
17252  if(!TrainController->CheckSessionLockedRoutes(0, InFile))
17253  {
17254  InFile.close();
17255  Utilities->CallLogPop(1255);
17256  return false;
17257  }
17258  if(InFile.fail())
17259  {
17260  InFile.close();
17261  Utilities->CallLogPop(1256);
17262  return false;
17263  }
17264  // check ContinuationAutoSigs
17265  if(!Utilities->CheckAndCompareFileString(InFile, "***ContinuationAutoSigEntries***"))
17266  {
17267  InFile.close();
17268  Utilities->CallLogPop(1257);
17269  return false;
17270  }
17272  {
17273  InFile.close();
17274  Utilities->CallLogPop(1258);
17275  return false;
17276  }
17277  if(InFile.fail())
17278  {
17279  InFile.close();
17280  Utilities->CallLogPop(1259);
17281  return false;
17282  }
17283  // check BarriersDownVector, but ensure backwards compatibility with earlier files which don't have this section
17284  AnsiString TempString = Utilities->LoadFileString(InFile);
17285  if((TempString != "***BarriersDownVector***") && (TempString != "***Timetable***"))
17286  {
17287  InFile.close();
17288  Utilities->CallLogPop(1964);
17289  return false;
17290  }
17291  if(TempString == "***BarriersDownVector***")
17292  {
17293  if(!Track->CheckActiveLCVector(0, InFile))
17294  {
17295  InFile.close();
17296  Utilities->CallLogPop(1965);
17297  return false;
17298  }
17299  if(InFile.fail())
17300  {
17301  InFile.close();
17302  Utilities->CallLogPop(1966);
17303  return false;
17304  }
17305  if(!Utilities->CheckAndCompareFileString(InFile, "***Timetable***"))
17306  {
17307  InFile.close();
17308  Utilities->CallLogPop(1260);
17309  return false;
17310  }
17311  }
17312  // check timetable (marker string already checked immediately above)
17313  if(!CheckTimetableFromSessionFile(0, InFile))
17314  {
17315  InFile.close();
17316  Utilities->CallLogPop(1261);
17317  return false;
17318  }
17319  if(InFile.fail())
17320  {
17321  InFile.close();
17322  Utilities->CallLogPop(1262);
17323  return false;
17324  }
17325  }
17326  else
17327  {
17328  InFile.close();
17329  ShowMessage("Session file failed to open - reason not known, unable to load session.");
17330  Utilities->CallLogPop(1263);
17331  return false;
17332  }
17333 
17334 // now ready for the 2nd pass for timetable loading and checking
17335  InFile.close();
17336  InFile.open(FileName.c_str());
17337  if(InFile.is_open())
17338  {
17340  {
17341  InFile.close();
17342  Utilities->CallLogPop(1264);
17343  return false;
17344  }
17345  if(!CheckInterface(1, InFile))
17346  {
17347  InFile.close();
17348  Utilities->CallLogPop(1265);
17349  return false;
17350  }
17351  // load track elements
17352  if(!Utilities->CheckAndCompareFileString(InFile, "***Track***"))
17353  {
17354  InFile.close();
17355  Utilities->CallLogPop(1266);
17356  return false;
17357  }
17358  bool GraphicsFollow = false;
17359  Track->LoadTrack(2, InFile, GraphicsFollow); // load the track this time
17360  if(InFile.fail())
17361  {
17362  InFile.close();
17363  Utilities->CallLogPop(1267);
17364  return false;
17365  }
17366  // check text elements
17367  if(!Utilities->CheckAndCompareFileString(InFile, "***Text***"))
17368  {
17369  InFile.close();
17370  Utilities->CallLogPop(1268);
17371  return false;
17372  }
17373  if(!TextHandler->CheckTextElementsInFile(2, InFile))
17374  {
17375  InFile.close();
17376  Utilities->CallLogPop(1269);
17377  return false;
17378  }
17379  if(InFile.fail())
17380  {
17381  InFile.close();
17382  Utilities->CallLogPop(1270);
17383  return false;
17384  }
17385  // check PrefDir elements
17386  if(!Utilities->CheckAndCompareFileString(InFile, "***PrefDirs***"))
17387  {
17388  InFile.close();
17389  Utilities->CallLogPop(1271);
17390  return false;
17391  }
17392  if(!EveryPrefDir->CheckOnePrefDir(2, NumberOfActiveElements, InFile))
17393  {
17394  InFile.close();
17395  Utilities->CallLogPop(1272);
17396  return false;
17397  }
17398  if(InFile.fail())
17399  {
17400  InFile.close();
17401  Utilities->CallLogPop(1273);
17402  return false;
17403  }
17404  // check graphics
17405  if(GraphicsFollow)
17406  {
17407  if(!Track->CheckUserGraphics(2, InFile, CurDir + "\\" + USERGRAPHICS_DIR_NAME)) // include path to Graphics folder
17408  {
17409  InFile.close();
17410  Utilities->CallLogPop(2189);
17411  return false;
17412  }
17413  if(InFile.fail())
17414  {
17415  InFile.close();
17416  Utilities->CallLogPop(2190);
17417  return false;
17418  }
17419  }
17420  // check routes
17421  if(!Utilities->CheckAndCompareFileString(InFile, "***Routes***"))
17422  {
17423  InFile.close();
17424  Utilities->CallLogPop(1274);
17425  return false;
17426  }
17427  if(!AllRoutes->CheckRoutes(1, NumberOfActiveElements, InFile))
17428  {
17429  InFile.close();
17430  Utilities->CallLogPop(1275);
17431  return false;
17432  }
17433  if(InFile.fail())
17434  {
17435  InFile.close();
17436  Utilities->CallLogPop(1276);
17437  return false;
17438  }
17439  // check LockedRoutes
17440  if(!Utilities->CheckAndCompareFileString(InFile, "***Locked routes***"))
17441  {
17442  InFile.close();
17443  Utilities->CallLogPop(1277);
17444  return false;
17445  }
17446  if(!TrainController->CheckSessionLockedRoutes(1, InFile))
17447  {
17448  InFile.close();
17449  Utilities->CallLogPop(1278);
17450  return false;
17451  }
17452  if(InFile.fail())
17453  {
17454  InFile.close();
17455  Utilities->CallLogPop(1279);
17456  return false;
17457  }
17458  // check ContinuationAutoSigs
17459  if(!Utilities->CheckAndCompareFileString(InFile, "***ContinuationAutoSigEntries***"))
17460  {
17461  InFile.close();
17462  Utilities->CallLogPop(1280);
17463  return false;
17464  }
17466  {
17467  InFile.close();
17468  Utilities->CallLogPop(1281);
17469  return false;
17470  }
17471  if(InFile.fail())
17472  {
17473  InFile.close();
17474  Utilities->CallLogPop(1282);
17475  return false;
17476  }
17477  // check BarriersDownVector, but ensure backwards compatibility with earlier files which don't have this section
17478  AnsiString TempString = Utilities->LoadFileString(InFile);
17479  if((TempString != "***BarriersDownVector***") && (TempString != "***Timetable***"))
17480  {
17481  InFile.close();
17482  Utilities->CallLogPop(1967);
17483  return false;
17484  }
17485  if(TempString == "***BarriersDownVector***")
17486  {
17487  if(!Track->CheckActiveLCVector(0, InFile))
17488  {
17489  InFile.close();
17490  Utilities->CallLogPop(1968);
17491  return false;
17492  }
17493  if(InFile.fail())
17494  {
17495  InFile.close();
17496  Utilities->CallLogPop(1969);
17497  return false;
17498  }
17499  if(!Utilities->CheckAndCompareFileString(InFile, "***Timetable***"))
17500  {
17501  InFile.close();
17502  Utilities->CallLogPop(1283);
17503  return false;
17504  }
17505  }
17506  // check timetable (marker string already checked)
17507  if(!LoadTimetableFromSessionFile(1, InFile))
17508  {
17509  InFile.close();
17510  Utilities->CallLogPop(1284);
17511  return false;
17512  }
17513  if(InFile.fail())
17514  {
17515  InFile.close();
17516  Utilities->CallLogPop(1285);
17517  return false;
17518  }
17519  // check timetable clock
17520  if(!Utilities->CheckAndCompareFileString(InFile, "***TimetableClock***"))
17521  {
17522  InFile.close();
17523  Utilities->CallLogPop(1286);
17524  return false;
17525  }
17526  if(!Utilities->CheckFileDouble(InFile))
17527  {
17528  InFile.close();
17529  Utilities->CallLogPop(1287);
17530  return false;
17531  }
17532  // check trains
17533  if(!Utilities->CheckAndCompareFileString(InFile, "***Trains***"))
17534  {
17535  InFile.close();
17536  Utilities->CallLogPop(1288);
17537  return false;
17538  }
17539  if(!TrainController->CheckSessionTrains(0, InFile))
17540  {
17541  InFile.close();
17542  Utilities->CallLogPop(1289);
17543  return false;
17544  }
17545  if(InFile.fail())
17546  {
17547  InFile.close();
17548  Utilities->CallLogPop(1290);
17549  return false;
17550  }
17551  if(!Utilities->CheckAndCompareFileString(InFile, "***Performance file***"))
17552  {
17553  InFile.close();
17554  Utilities->CallLogPop(1291);
17555  return false;
17556  }
17557  if(!CheckPerformanceFile(0, InFile))
17558  {
17559  InFile.close();
17560  Utilities->CallLogPop(1292);
17561  return false;
17562  }
17563  char TempChar;
17564  InFile.get(TempChar);
17565  while(!InFile.eof() && ((TempChar == '\n') || (TempChar == '\0'))) // when emerge from here either have eof or '*'
17566  {
17567  InFile.get(TempChar);
17568  }
17569  if(!InFile.eof()) // additional checks needed
17570  {
17571  if(!Utilities->CheckFileString(InFile))
17572  {
17573  InFile.close();
17574  Utilities->CallLogPop(2198);
17575  return false;
17576  }
17577  if(!Utilities->CheckFileInt(InFile, 0, 1000000)) // TrainController->AvHoursIntValue
17578  {
17579  InFile.close();
17580  Utilities->CallLogPop(2199);
17581  return false;
17582  }
17583  if(!Utilities->CheckFileInt(InFile, 0, 1000000)) // number of train failures
17584  {
17585  InFile.close();
17586  Utilities->CallLogPop(2200);
17587  return false;
17588  }
17589  // now check any failed trains along with their OriginalPowerAtRail values
17590  Utilities->CheckFileString(InFile); // discard "***Failed Trains***"
17591  int IDVal;
17592  if(!Utilities->CheckAndReadFileInt(InFile, -1, 1000000, IDVal)) // train ID or -1 for no more failed trains,
17593  {
17594  InFile.close();
17595  Utilities->CallLogPop(2201);
17596  return false;
17597  }
17598  double PowerDouble;
17599  while(IDVal != -1)
17600  {
17601  Utilities->CheckFileDouble(InFile); // original power
17602  if(!Utilities->CheckAndReadFileInt(InFile, -1, 1000000, IDVal))
17603  {
17604  InFile.close();
17605  Utilities->CallLogPop(2202);
17606  return false;
17607  }
17608  }
17609  }
17610  InFile.close();
17611  }
17612  else
17613  {
17614  InFile.close();
17615  Utilities->CallLogPop(1293);
17616  return false;
17617  }
17618  Utilities->CallLogPop(1294);
17619  return true;
17620 }
17621 
17622 // ---------------------------------------------------------------------------
17623 
17624 void TInterface::LoadPerformanceFile(int Caller, std::ifstream &InFile)
17625  // Note that the file integrity has already been checked using CheckPerformanceFile
17626 {
17627  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadPerformanceFile");
17628  AnsiString TempString = "", Line1 = "", Line2 = "", Line3 = "", Line4 = "", Line5 = "";
17629  char *Buffer = new char[1000];
17630  char TempChar;
17631 
17632  InFile.get(TempChar); // '\n'
17633  InFile.getline(Buffer, 1000);
17634  TempString = AnsiString(Buffer);
17635  while(TempString != "***End of performance file***")
17636  {
17637  PerformanceLogBox->Lines->Add(TempString);
17638  Utilities->PerformanceFile << TempString.c_str() << '\n';
17639  InFile.getline(Buffer, 1000);
17640  TempString = AnsiString(Buffer);
17641  }
17642  delete Buffer;
17643  Utilities->CallLogPop(1295);
17644 }
17645 
17646 // ---------------------------------------------------------------------------
17647 
17648 bool TInterface::CheckPerformanceFile(int Caller, std::ifstream &InFile)
17649 {
17650  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",CheckPerformanceFile");
17651  AnsiString TempString = "";
17652  char TempChar;
17653 
17654  InFile.get(TempChar);
17655  if(TempChar != '\n')
17656  {
17657  Utilities->CallLogPop(1296);
17658  return false;
17659  }
17660  if(!Utilities->CheckAndReadFileString(InFile, TempString))
17661  {
17662  Utilities->CallLogPop(1297);
17663  return false;
17664  }
17665  while(TempString != "***End of performance file***")
17666  {
17667  if(!Utilities->CheckAndReadFileString(InFile, TempString))
17668  {
17669  Utilities->CallLogPop(1298);
17670  return false;
17671  }
17672  }
17673  Utilities->CallLogPop(1299);
17674  return true;
17675 }
17676 
17677 // ---------------------------------------------------------------------------
17678 
17679 void TInterface::SavePerformanceFile(int Caller, std::ofstream &OutFile)
17680 {
17681  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SavePerformanceFile");
17682  AnsiString Text = PerformanceLogBox->Text;
17683 
17684  while(Text != "")
17685  {
17686  AnsiString OneLine = Text.SubString(1, Text.Pos('\x0D'));
17687  while((OneLine.Length() > 0) && OneLine[OneLine.Length()] < ' ')
17688  OneLine.SetLength(OneLine.Length() - 1); // get rid of trailing control characters
17689  Text = Text.SubString(Text.Pos('\x0D'), Text.Length());
17690  while((Text.Length() > 0) && Text[1] < ' ')
17691  Text = Text.SubString(2, (Text.Length() - 1)); // get rid of leading control characters
17692  OutFile << OneLine.c_str() << '\n';
17693  }
17694  Utilities->CallLogPop(1300);
17695 }
17696 
17697 // ---------------------------------------------------------------------------
17698 
17700 {
17701  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetRouteButtonsInfoCaptionAndRouteNotStarted");
17702  if(EveryPrefDir->PrefDirSize() > 0)
17703  {
17704  if(AutoSigsFlag)
17705  {
17706  AutoSigsButton->Enabled = false;
17707  SigPrefButton->Enabled = true;
17708  UnrestrictedButton->Enabled = true;
17709  InfoPanel->Visible = true;
17710  if(Level2OperMode == PreStart)
17711  InfoPanel->Caption = "PRE-START: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
17712  else
17713  InfoPanel->Caption = "OPERATING: Select AUTOMATIC SIGNAL ROUTE start signal, or left click points to change manually";
17714  InfoCaptionStore = InfoPanel->Caption;
17715  }
17716  else if(ConsecSignalsRoute) // PreferredRoute always same as ConsecSignalsRoute
17717  {
17718  AutoSigsButton->Enabled = true;
17719  SigPrefButton->Enabled = false;
17720  UnrestrictedButton->Enabled = true;
17721  InfoPanel->Visible = true;
17722  if(Level2OperMode == PreStart)
17723  InfoPanel->Caption = "PRE-START: Select PREFERRED ROUTE start signal, or left click points to change manually";
17724  else
17725  InfoPanel->Caption = "OPERATING: Select PREFERRED ROUTE start signal, or left click points to change manually";
17726  InfoCaptionStore = InfoPanel->Caption;
17727  }
17728  else
17729  {
17730  AutoSigsButton->Enabled = true;
17731  SigPrefButton->Enabled = true;
17732  UnrestrictedButton->Enabled = false;
17733  InfoPanel->Visible = true;
17734  if(Level2OperMode == PreStart)
17735  InfoPanel->Caption = "PRE-START: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
17736  else
17737  InfoPanel->Caption = "OPERATING: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
17738  InfoCaptionStore = InfoPanel->Caption;
17739  }
17740  }
17741  else
17742  {
17743  AutoSigsButton->Enabled = false;
17744  SigPrefButton->Enabled = false;
17745  UnrestrictedButton->Enabled = false;
17746  InfoPanel->Visible = true;
17747  if(Level2OperMode == PreStart)
17748  InfoPanel->Caption = "PRE-START: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
17749  else
17750  InfoPanel->Caption = "OPERATING: Select UNRESTRICTED ROUTE start location, or left click points to change manually";
17751  InfoCaptionStore = InfoPanel->Caption;
17752  }
17754  {
17755  RouteCancelButton->Enabled = true;
17756  }
17757  else
17758  {
17759  RouteCancelButton->Enabled = false;
17760  }
17762  AutoRouteStartMarker->PlotOriginal(37, Display); // so start marker will replot if had selected start before pause & zoom
17765  Utilities->CallLogPop(1301);
17766 }
17767 
17768 // ---------------------------------------------------------------------------
17769 
17771 {
17772  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetPausedOrZoomedInfoCaption");
17773  if(Display->ZoomOutFlag)
17774  {
17775  InfoPanel->Visible = true;
17776  InfoPanel->Caption = "Left click screen to zoom in at that position";
17777  }
17778  else if(Level2OperMode == Paused)
17779  {
17780  InfoPanel->Visible = true;
17781  InfoPanel->Caption = "PAUSED: Railway state changes disabled";
17782  }
17783 // otherwise do nothing
17784  Utilities->CallLogPop(1302);
17785 }
17786 
17787 // ---------------------------------------------------------------------------
17788 
17790 {
17791  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",DisableRouteButtons");
17792  RouteCancelButton->Enabled = false;
17793  AutoSigsButton->Enabled = false;
17794  SigPrefButton->Enabled = false;
17795  UnrestrictedButton->Enabled = false;
17796  Utilities->CallLogPop(1303);
17797 }
17798 
17799 // ---------------------------------------------------------------------------
17800 
17802  // no need for call logging as already failed
17803 {
17804 /*
17805  In order to reload as a session file:
17806 
17807  NB: Don't change it to a .txt file, as the '\0' characters [shown as a small square in wordpad] will be changed to spaces if it is subsequently saved
17808  strip out:-
17809 
17810  [since adding user graphics after prefdirs need to take this into account]
17811 
17812  up to but excluding ***Interface***
17813  from & including ***ConstructPrefDir PrefDirVector***
17814  to but excluding ***PrefDirs***
17815  if there is a single line ***UserGraphics*** delete it (won't be present if no graphics)
17816  from & including ***ConstructRoute PrefDirVector***
17817  to but excluding ***Routes***
17818  from & including ***ChangingLCVector*** to but excluding ***Timetable*** [if have ***No timetable loaded*** then can't use as a session file]
17819  from & including ***No editing timetable*** or ***Editing timetable - [title]***
17820  to but excluding ***TimetableClock***
17821  and save as a .ssn file.
17822 
17823  In order to load as a railway file:
17824 
17825  NB: Don't change it to a .txt file, as the '\0' characters will be changed to spaces if it is subsequently saved
17826 
17827  note or copy the version information at the top of the file
17828  copy the two numbers on rows 7 & 8 below ***Interface*** (i.e ***Interface*** = row 0) on their own lines immediately after the ***Track*** line (these become DisplayOffsetH & V)
17829  strip out up to but excluding ***Track*** - this is needed to keep the \0 entry at end of ***Track*** [shown as a small square in wordpad]
17830  add the version number either before or instead of ***Track***, ensuring that the \0 is retained
17831  the next line after the two insertions should contain the number of active elements.
17832  strip out ***Text*** including the \0
17833  strip out from & including ***ConstructPrefDir PrefDirVector*** to & including ***PrefDirs*** (and the \0's)
17834  strip out ***UserGraphics*** including the \0
17835  strip out from & including ***ConstructRoute PrefDirVector*** to the end of the file
17836  rename as .dev or .rly file
17837 
17838  BUT - note that signals (and points, though they won't show) will be set as they were left. To reset to red, load a suitable timetable & select
17839  'Operate' then 'Exit operation'.
17840 */
17841 
17842 /*
17843  In order to extract a timetable:
17844 
17845  NB: Don't change it to a .txt file, as the '\0' characters will be changed to spaces if it is subsequently saved
17846 
17847  set wordwrap to window on
17848  strip out all to and including ***Timetable*** or ***Editing timetable.... depending which is to be saved
17849  ensure any text before start time ends with /0, otherwise don't need the \0
17850  strip out all after the final /0 immediately before ***End*** or ***End of timetable***, but ensure leave the final /0
17851  save as a .ttb file
17852 */
17853 
17854  Screen->Cursor = TCursor(-11); // Hourglass;
17855  AnsiString ErrorFileStr = CurDir + "\\errorlog.err";
17856  std::ofstream ErrorFile(ErrorFileStr.c_str());
17857 
17858  if(!(ErrorFile.fail()))
17859  {
17860 // save mouse position relative to mainscreen
17861  int ScreenX = Mouse->CursorPos.x - MainScreen->ClientOrigin.x;
17862  int ScreenY = Mouse->CursorPos.y - MainScreen->ClientOrigin.y;
17863  AnsiString MouseStr = "Posx: " + AnsiString(ScreenX) + "; Posy: " + AnsiString(ScreenY);
17864  Utilities->SaveFileString(ErrorFile, MouseStr);
17865  Utilities->SaveFileInt(ErrorFile, MissedTicks);
17866  Utilities->SaveFileInt(ErrorFile, TotalTicks);
17867 
17868 // save call stack
17869  Utilities->SaveFileString(ErrorFile, "***Call stack***");
17870  for(unsigned int x = 0; x < Utilities->CallLog.size(); x++)
17871  {
17872  AnsiString Item = Utilities->CallLog.at(x);
17873  ErrorFile << Item.c_str() << '\n';
17874  }
17875 // save event log
17876  Utilities->SaveFileString(ErrorFile, "***Event log***");
17877  for(unsigned int x = 0; x < Utilities->EventLog.size(); x++)
17878  {
17879  AnsiString Item = Utilities->EventLog.at(x);
17880  ErrorFile << Item.c_str() << '\n';
17881  }
17882 // save interface
17883  Utilities->SaveFileString(ErrorFile, "***Interface***");
17884  SaveInterface(1, ErrorFile);
17885 // save track elements
17886  Utilities->SaveFileString(ErrorFile, "***Track***");
17887  if(Track->UserGraphicVector.empty())
17888  {
17889  Track->SaveTrack(2, ErrorFile, false); // false for no graphics (**Active elements** saved as marker)
17890  }
17891  else
17892  {
17893  Track->SaveTrack(12, ErrorFile, true); // true for graphics to be saved (**Active elements**1 saved as marker)
17894  }
17895 // save text elements
17896  Utilities->SaveFileString(ErrorFile, "***Text***");
17897  TextHandler->SaveText(3, ErrorFile);
17898 // save ConstructPrefDir PrefDirVector elements
17899  Utilities->SaveFileString(ErrorFile, "***ConstructPrefDir PrefDirVector***");
17900  ConstructPrefDir->SavePrefDirVector(7, ErrorFile);
17901 // save ConstructPrefDir SearchVector elements
17902  Utilities->SaveFileString(ErrorFile, "***ConstructPrefDir SearchVector***");
17903  ConstructPrefDir->SaveSearchVector(0, ErrorFile);
17904 // save EveryPrefDir elements
17905  Utilities->SaveFileString(ErrorFile, "***PrefDirs***");
17906  EveryPrefDir->SavePrefDirVector(3, ErrorFile);
17907  if(!Track->UserGraphicVector.empty())
17908  {
17909  // save user graphics
17910  Utilities->SaveFileString(ErrorFile, "***UserGraphics***");
17911  Track->SaveUserGraphics(3, ErrorFile);
17912  }
17913 // save ConstructRoute PrefDirVector
17914  Utilities->SaveFileString(ErrorFile, "***ConstructRoute PrefDirVector***");
17915  ConstructRoute->SavePrefDirVector(4, ErrorFile);
17916 // save ConstructRoute SearchVector
17917  Utilities->SaveFileString(ErrorFile, "***ConstructRoute SearchVector***");
17918  ConstructRoute->SaveSearchVector(1, ErrorFile);
17919 // save AllRoutes
17920  Utilities->SaveFileString(ErrorFile, "***Routes***");
17921  AllRoutes->SaveRoutes(1, ErrorFile);
17922 // save LockedRoutes
17923  Utilities->SaveFileString(ErrorFile, "***Locked routes***");
17925 // save ContinuationAutoSigEntries
17926  Utilities->SaveFileString(ErrorFile, "***ContinuationAutoSigEntries***");
17928 // save BarriersDownVector
17929  Utilities->SaveFileString(ErrorFile, "***BarriersDownVector***");
17930  Track->SaveSessionBarriersDownVector(1, ErrorFile);
17931 // save ChangingLCVector
17932  Utilities->SaveFileString(ErrorFile, "***ChangingLCVector***");
17933  Track->SaveChangingLCVector(0, ErrorFile);
17934 // save loaded timetable
17935  if(TimetableTitle == "")
17936  Utilities->SaveFileString(ErrorFile, "***No timetable loaded***");
17937  else
17938  {
17939  Utilities->SaveFileString(ErrorFile, "***Timetable***");
17940  if(!(SaveTimetableToSessionFile(1, ErrorFile, ErrorFileStr)))
17941  {
17942  Utilities->SaveFileString(ErrorFile, "***Loaded timetable failed to save***");
17943  }
17944  }
17945 // save editing timetable
17946  if(CreateEditTTTitle == "")
17947  Utilities->SaveFileString(ErrorFile, "***No editing timetable***");
17948  else
17949  {
17950  Utilities->SaveFileString(ErrorFile, "***Editing timetable - " + CreateEditTTTitle + "***");
17951  if(!(SaveTimetableToErrorFile(1, ErrorFile, ErrorFileStr, CreateEditTTFileName)))
17952  {
17953  Utilities->SaveFileString(ErrorFile, "***Editing timetable failed to save***");
17954  }
17955  }
17956 // save TimetableClock
17957  Utilities->SaveFileString(ErrorFile, "***TimetableClock***");
17958  Utilities->SaveFileDouble(ErrorFile, double(TrainController->TTClockTime));
17959 // save trains
17960  Utilities->SaveFileString(ErrorFile, "***Trains***");
17961  TrainController->SaveSessionTrains(1, ErrorFile);
17962 // save performance file
17963  Utilities->SaveFileString(ErrorFile, "***Performance file***");
17964  SavePerformanceFile(1, ErrorFile);
17965  Utilities->SaveFileString(ErrorFile, "***End of performance file***");
17966 // addition at v2.4.1 to save TrainController->AvHoursIntValue + any future additions
17967  Utilities->SaveFileString(ErrorFile, "***Additions after v2.3.1***");
17970  Utilities->SaveFileString(ErrorFile, "***Failed Trains***");
17971  for(unsigned int x = 0; x < TrainController->TrainVector.size(); x++)
17972  {
17974  {
17977  }
17978  }
17979  Utilities->SaveFileInt(ErrorFile, -1); // marker for end of failed trains
17980  Utilities->SaveFileString(ErrorFile, "End of file at v2.4.1");
17981 // end of v2.4.1 addition
17982 
17983  ErrorFile.close();
17984  }
17985  else
17986  {
17987  TrainController->StopTTClockMessage(6, "Error file failed to open, error log won't be saved.");
17988  }
17989  Screen->Cursor = TCursor(-2); // Arrow
17990 }
17991 
17992 // ---------------------------------------------------------------------------
17993 
17994 void TInterface::SaveTempTimetableFile(int Caller, AnsiString InFileName)
17995  // the .ttb section is delimited by '\n' followed by "***End***"
17996  // first create a .ttb file in the working folder exactly like the original
17997 
17998  // Note: this type of file use failed when used to resave timetable.tmp from temp .ttb file, but changed that to avoid so many rapid
17999  // file actions in quick succession & been OK since then, but nevertheless keep the 10 retries before giving message to be on safe side
18000 {
18001  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveTempTimetableFile");
18002  if((TempTTFileName != "") && FileExists(TempTTFileName))
18003  {
18004  DeleteFile(TempTTFileName);
18005  }
18006  int TempTTFileNumber = 0;
18007 
18008  while(FileExists(CurDir + "\\TmpTT" + AnsiString(TempTTFileNumber) + ".tmp"))
18009  {
18010  TempTTFileNumber++;
18011  }
18012  TempTTFileName = CurDir + "\\TmpTT" + AnsiString(TempTTFileNumber) + ".tmp";
18013  int InHandle = FileOpen(InFileName, fmOpenRead);
18014  int Count = 0;
18015 
18016  while(InHandle < 0) // sometimes fails, have 10 retries before giving message
18017  {
18018  InHandle = FileOpen(InFileName, fmOpenRead);
18019  Count++;
18020  Delay(2, 50); // 50mSec delay between tries
18021  if(Count > 10)
18022  {
18023  ShowMessage("Failed to open timetable file, make sure it's not open in another application");
18024  Utilities->CallLogPop(1400);
18025  return;
18026  }
18027  }
18028  int OutHandle = FileCreate(TempTTFileName);
18029 
18030  Count = 0;
18031  while(OutHandle < 0) // sometimes fails, have 10 retries before giving message
18032  {
18033  OutHandle = FileCreate(TempTTFileName);
18034  Count++;
18035  Delay(3, 50); // 50mSec delay between tries
18036  if(Count > 10)
18037  {
18038  ShowMessage("Failed to save temporary timetable file, sessions can't be saved - try again, may only be a temporary problem");
18039  FileClose(InHandle);
18040  Utilities->CallLogPop(1401);
18041  return;
18042  }
18043  }
18044  int CountIn, CountOut;
18045  char *Buffer = new char[10000]; // can't use LoadFileString as that expects a '\0' delimiter
18046 
18047  while(true)
18048  {
18049  CountIn = FileRead(InHandle, Buffer, 10000);
18050  CountOut = FileWrite(OutHandle, Buffer, CountIn);
18051  if(CountOut != CountIn)
18052  {
18053  ShowMessage("Error in writing to the temporary timetable file, sessions can't be saved - try again, may only be a temporary problem");
18054  delete Buffer;
18055  FileClose(InHandle);
18056  FileClose(OutHandle);
18057  Utilities->CallLogPop(1402);
18058  return;
18059  }
18060  if(CountIn < 10000)
18061  break;
18062  }
18063  delete Buffer;
18064  FileClose(InHandle);
18065  FileClose(OutHandle);
18066  Utilities->CallLogPop(1403);
18067 }
18068 
18069 // ---------------------------------------------------------------------------
18070 
18071 void TInterface::SetTrackLengths(int Caller, int Distance, int SpeedLimit) // Distance & SpeedLimit are -1 for no change to that parameter
18072 /*
18073  Rules: Platforms are fixed length elements of 100m and aren't changed - no, see note below. Variable length elements can't be less than 20m.
18074  above changed in v2.4.0 to be variable as other track, but if <50m or >200m a warning is given
18075 
18076  Enter with DistanceVector containing the PrefDir to be set, Distance containing the required sum of all element lengths,
18077  and SpeedLimit containing the speed limit. If either of these is -1 (can be -1 separately) then no change is to be made to it.
18078  Return for an empty DistanceVector. Deal first with a single element in the vector, giving a message if there is a platform there.
18079  Now set exit link position (XLinkPos) value for the first element in DistanceVector by checking which link connects to the second
18080  element in the vector, and give a warning message if fail to find it. Now have to make two passes through the vector, firstly to
18081  sum the fixed lengths, count the number of variable length elements and set the speed limit, and secondly to set the lengths.
18082  Firstly store the first XLinkPos so don't have to recalculate it for the second pass. On the first pass examine each element,
18083  incrementing the variable element count or summing the fixed length count as go along, and setting the speed limits providing
18084  SpeedLimit isn't -1. If Distance was -1 then still go through but don't count anything, just set the speed limits. Recalculate
18085  the next XLinkPos for each succeeding element.
18086  After the first pass return if Distance was -1 as in that case have now finished. Otherwise check if the distance to be set is less than
18087  the minimum possible within the rules, and if so give a message and return. Also give a warning message if there aren't any variable length
18088  elements. Now enter the second pass. In this the length of each variable element is set to int(RemainingDistance/RemainingVarElements) and
18089  fixed length elements are ignored. After each variable length element is set the RemainingDistance and RemainingVarElements are recalculated
18090  ready for the next setting. In this way there is never more than 1 difference between any two variable length elements and the total
18091  distance sums exactly to the value required. A check is made after every variable length element has been set to see whether RemainingDistance
18092  and RemainingVarElements are zero, and if they don't reach zero together (which they should after the last variable length element has
18093  been set), an error message is given.
18094 */
18095 
18096 {
18097  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SetLengths," + AnsiString(Distance) + "," + AnsiString(SpeedLimit));
18098  bool FoundFlag;
18099 
18100 // ResetDistanceElements(4);
18101  if(ConstructPrefDir->PrefDirSize() == 0)
18102  {
18103  Utilities->CallLogPop(608);
18104  return;
18105  }
18106 // must have PrefDir size of at least 2
18107 
18108 // first pass to count number of variable length elements, sum fixed lengths & set speed limit
18109 // for version in v2.4.0 have no fixed length elements but leave code as is as much as possible
18110  int VarElements = 0; // FixedLength = 0; drop this in v2.4.0
18111  bool NamedLocPresent = false;
18112 
18113  for(unsigned int x = 0; x < ConstructPrefDir->PrefDirSize(); x++)
18114  {
18115  TPrefDirElement PrefDirElement = ConstructPrefDir->GetFixedPrefDirElementAt(167, x);
18116  TTrackElement & TE = Track->TrackElementAt(34, Track->GetVectorPositionFromTrackMap(28, PrefDirElement.HLoc, PrefDirElement.VLoc, FoundFlag));
18117  if(!FoundFlag)
18118  {
18119  throw Exception("Error - failed to find track element at " + AnsiString(TE.HLoc) + " & " + AnsiString(TE.VLoc) + " in SetLengths");
18120  }
18121  if((Distance != -1) && (!Track->IsPlatformOrNamedNonStationLocationPresent(2, TE.HLoc, TE.VLoc)))
18122  VarElements++;
18123  else if((Distance != -1) && (Track->IsPlatformOrNamedNonStationLocationPresent(3, TE.HLoc, TE.VLoc)))
18124  {
18125  VarElements++; // added in v2.4.0 for no fixed elements
18126  NamedLocPresent = true;
18127 // FixedLength+= DefaultTrackLength; dropped in v2.4.0 for no fixed elements
18128  }
18129 
18130  if((PrefDirElement.GetELinkPos() < 2) && (PrefDirElement.GetXLinkPos() < 2)) // could be points
18131  {
18132  if(SpeedLimit != -1)
18133  TE.SpeedLimit01 = SpeedLimit;
18134  }
18135  else
18136  {
18137  if(SpeedLimit != -1)
18138  TE.SpeedLimit23 = SpeedLimit;
18139  }
18140  }
18141  if(Distance == -1) // can't return before this as need to set speed limits
18142  {
18143  Utilities->CallLogPop(612);
18144  return;
18145  }
18146 
18147  if((NamedLocPresent) && (VarElements > 0) && ((Distance / VarElements) < 50)) // these two additions are for in v2.4.0
18148  {
18149  ShowMessage("Note: Named location elements are quite short. If they are too short the simulation might depart too far from reality.");
18150  }
18151 
18152  if((NamedLocPresent) && (VarElements > 0) && ((Distance / VarElements) > 200))
18153  {
18154  ShowMessage("Note: Named location elements are quite long. If they are too long the simulation might depart too far from reality.");
18155  }
18156 
18157 /* if(NamedLocPresent) as was
18158  {
18159  ShowMessage("Named location lengths won't be changed");
18160  }
18161 */
18162 
18163  if((VarElements * 20) > Distance) // removed '+ FixedLength'
18164  {
18165  ShowMessage("Required distance is less than the minimum, will set each element to the minimum (20m)");
18166  Distance = (VarElements * 20); // removed '+ FixedLength'
18167  }
18168  if(VarElements == 0)
18169  {
18170 // ShowMessage("Unable to set distance as all elements are of fixed length"); as was
18171  ShowMessage("No elements selected"); // probably don't need this but include for safety
18172  Utilities->CallLogPop(613);
18173  return;
18174  }
18175 
18176 // second pass, set variable lengths
18177  int RemainingDistance = Distance, RemainingVarElements = VarElements, NextLength = RemainingDistance / VarElements; // removed ' - FixedLength'
18178 
18179  for(unsigned int x = 0; x < ConstructPrefDir->PrefDirSize(); x++)
18180  {
18181  TPrefDirElement PrefDirElement = ConstructPrefDir->GetFixedPrefDirElementAt(168, x);
18182  TTrackElement & TE = Track->TrackElementAt(35, Track->GetVectorPositionFromTrackMap(29, PrefDirElement.HLoc, PrefDirElement.VLoc, FoundFlag));
18183 // if(!Track->IsPlatformOrNamedNonStationLocationPresent(4, TE.HLoc, TE.VLoc)) //variable lengths dropped in v2.4.0
18184 // {
18185  if(NextLength < 20)
18186  NextLength = 20; // added for safety
18187  if(TE.TrackType == Points)
18188  {
18189  if((PrefDirElement.GetELinkPos() == 1) || (PrefDirElement.GetXLinkPos() == 1))
18190  {
18191  TE.Length01 = NextLength;
18192  }
18193  else
18194  {
18195  TE.Length23 = NextLength;
18196  }
18197  }
18198  else
18199  {
18200  if(PrefDirElement.GetELinkPos() < 2)
18201  {
18202  TE.Length01 = NextLength;
18203  }
18204  else
18205  {
18206  TE.Length23 = NextLength;
18207  }
18208  }
18209  RemainingDistance -= NextLength;
18210  RemainingVarElements--;
18211  if(RemainingVarElements > 0)
18212  NextLength = RemainingDistance / RemainingVarElements;
18213  else
18214  NextLength = 20;
18215 
18216 /* removed these as using integer division & that sometimes problematic. None of these errors ever reported but be safe
18217  if((RemainingDistance == 0) && (RemainingVarElements != 0))
18218  {
18219  throw Exception("Error RemainingDistance == 0 & RemainingVarElements != 0");
18220  }
18221  if((RemainingDistance != 0) && (RemainingVarElements == 0))
18222  {
18223  throw Exception("Error RemainingDistance != 0 & RemainingVarElements == 0");
18224  }
18225 */
18226 // }
18227  }
18228  Utilities->CallLogPop(614);
18229 }
18230 
18231 // ---------------------------------------------------------------------------
18232 
18234 {
18235  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",SaveAsSubroutine");
18237  ShowMessage("Nothing to save!");
18238  else
18239  {
18240  if(Track->IsReadyForOperation(false))
18241  {
18242  SaveRailwayDialog->Filter = "Development file (*.dev)|*.dev|Railway file (*.rly)|*.rly";
18243  }
18244  else
18245  SaveRailwayDialog->Filter = "Development file (*.dev)|*.dev";
18246  if(SaveRailwayDialog->Execute())
18247  {
18248  if(SaveRailwayDialog->InitialDir != TPath::GetDirectoryName(SaveRailwayDialog->FileName))//new at v2.6.0 to retain a new directory
18249  {
18250  SaveRailwayDialog->InitialDir = TPath::GetDirectoryName(SaveRailwayDialog->FileName);
18251  LoadRailwayDialog->InitialDir = TPath::GetDirectoryName(SaveRailwayDialog->FileName);
18252  }
18253  Screen->Cursor = TCursor(-11); // Hourglass;
18254  TrainController->LogEvent("Save " + SaveRailwayDialog->FileName);
18255  AnsiString Extension = "";
18256  if(SaveRailwayDialog->FileName.Length() > 2)
18257  {
18258  Extension = AnsiString(SaveRailwayDialog->FileName).SubString(AnsiString(SaveRailwayDialog->FileName).Length() - 2, 3).UpperCase();
18259  }
18260  if((Extension == "DEV") || (Track->IsReadyForOperation(true) && (Extension == "RLY"))) //give duplicated location name message if appropriate
18261  {
18262  std::ofstream VecFile(AnsiString(SaveRailwayDialog->FileName).c_str());
18263  if(!(VecFile.fail()))
18264  {
18268  // save track elements
18269  if(Track->UserGraphicVector.empty())
18270  {
18271  Track->SaveTrack(1, VecFile, false); // false for no graphics (**Active elements** saved as marker)
18272  }
18273  else
18274  {
18275  Track->SaveTrack(13, VecFile, true); // true for graphics to be saved (**Active elements**1 saved as marker)
18276  }
18277  // save text elements
18278  TextHandler->SaveText(1, VecFile);
18279  // save PrefDir elements
18280  EveryPrefDir->SavePrefDirVector(1, VecFile);
18281  if(!Track->UserGraphicVector.empty())
18282  {
18283  // save user graphics
18284  Track->SaveUserGraphics(4, VecFile);
18285  }
18286  VecFile.close();
18287  SavedFileName = SaveRailwayDialog->FileName; // includes the full PrefDir
18288  if(SavedFileName != "") // shouldn't be "" at this stage but leave in as a safeguard
18289  {
18290  char LastChar = SavedFileName[SavedFileName.Length()];
18291  if((LastChar == 'y') || (LastChar == 'Y'))
18292  {
18293  RlyFile = true;
18294  }
18295  else
18296  {
18297  RlyFile = false;
18298  }
18299  }
18300  else
18301  {
18302  RlyFile = false;
18303  }
18304  FileChangedFlag = false;
18305  for(int x = SaveRailwayDialog->FileName.Length(); x > 0; x--)
18306  {
18307  if(SaveRailwayDialog->FileName[x] == '\\')
18308  {
18309  RailwayTitle = SaveRailwayDialog->FileName.SubString(x + 1, SaveRailwayDialog->FileName.Length() - x - 4);
18310  // TimetableTitle = ""; leave this as is, no need to unload a tt just because saved railway
18311  SetCaption(7);
18312  break;
18313  }
18314  }
18315  Level1Mode = BaseMode;
18316  SetLevel1Mode(13); // to disable the save option
18317  } // if(!(VecFile.fail()))
18318  else
18319  ShowMessage("File open failed prior to save");
18320  } // else following if(!Track->IsReadyForOperation() && (Extension != "DEV"))
18321  else
18322  {
18323  ShowMessage("Can't save: extension must be either '.dev', or '.rly' with railway ready for operation");
18324  }
18325  Screen->Cursor = TCursor(-2); // Arrow
18326  } //if(SaveRailwayDialog->Execute())
18327  }
18328  Utilities->CallLogPop(1546);
18329 }
18330 
18331 // ---------------------------------------------------------------------------
18332 
18334 { // no need for caller or log as only setting values
18335  CutMenuItem->Visible = true;
18336  CopyMenuItem->Visible = true;
18337  FlipMenuItem->Visible = true;
18338  MirrorMenuItem->Visible = true;
18339  RotRightMenuItem->Visible = true;
18340  RotLeftMenuItem->Visible = true;
18341  RotateMenuItem->Visible = true;
18342  PasteMenuItem->Visible = true;
18343 // PasteWithAttributesMenuItem->Visible = true; //added at v2.2.0
18344  DeleteMenuItem->Visible = true;
18345  SelectLengthsMenuItem->Visible = true;
18346  ReselectMenuItem->Visible = true;
18347 
18348  CutMenuItem->Enabled = false;
18349  CopyMenuItem->Enabled = false;
18350  FlipMenuItem->Enabled = false;
18351  MirrorMenuItem->Enabled = false;
18352  RotRightMenuItem->Enabled = false;
18353  RotLeftMenuItem->Enabled = false;
18354  RotateMenuItem->Enabled = false;
18355  PasteMenuItem->Enabled = false;
18356 // PasteWithAttributesMenuItem->Enabled = false; //new at v2.2.0
18357  DeleteMenuItem->Enabled = false;
18358  SelectLengthsMenuItem->Enabled = false;
18359  if(SelectionValid)
18360  ReselectMenuItem->Enabled = true;
18361  else
18362  ReselectMenuItem->Enabled = false;
18363 
18364  SelectBiDirPrefDirsMenuItem->Visible = false;
18365  CancelSelectionMenuItem->Enabled = true;
18366  SelectMenuItem->Enabled = true;
18367 
18368  if(NoRailway())
18369  {
18370  EditMenu->Enabled = false;
18371  }
18372  else
18373  EditMenu->Enabled = true;
18374 }
18375 
18376 // ---------------------------------------------------------------------------
18377 
18379 { // no need for caller or log as only setting values
18380  EditMenu->Enabled = true;
18381 
18382  CutMenuItem->Visible = false;
18383  CopyMenuItem->Visible = false;
18384  FlipMenuItem->Visible = false;
18385  MirrorMenuItem->Visible = false;
18386  RotRightMenuItem->Visible = false;
18387  RotLeftMenuItem->Visible = false;
18388  RotateMenuItem->Visible = false;
18389  PasteMenuItem->Visible = false;
18390 // PasteWithAttributesMenuItem->Visible = false; //added at v2.2.0
18391  DeleteMenuItem->Visible = false;
18392  SelectLengthsMenuItem->Visible = false;
18393  ReselectMenuItem->Visible = false;
18394 
18395  SelectBiDirPrefDirsMenuItem->Visible = true;
18396  SelectBiDirPrefDirsMenuItem->Enabled = false;
18397  CancelSelectionMenuItem->Enabled = true;
18398  SelectMenuItem->Enabled = true;
18399 }
18400 
18401 // ---------------------------------------------------------------------------
18402 
18404 {
18405  return ((Track->NoActiveOrInactiveTrack(5)) && (TextHandler->TextVectorSize(8) == 0) && Track->UserGraphicVector.empty());
18406 }
18407 
18408 // ---------------------------------------------------------------------------
18409 
18411 {
18412  SelectRect.left = 0;
18413  SelectRect.right = 0;
18414  SelectRect.top = 0;
18415  SelectRect.bottom = 0;
18416 }
18417 
18418 // ---------------------------------------------------------------------------
18419 
18420 bool TInterface::EraseLocationNameText(int Caller, AnsiString Name, int &HPos, int &VPos)
18421 { // return position of erased name in HPos & VPos, return true for found & erased
18422  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",EraseLocationNameText," + Name);
18423  bool TextFound = false;
18424 
18425 // if(Track->LocationNameMultiMap.find(Name) == Track->LocationNameMultiMap.end()) {} //name not in LocationNameMultiMap, so don't erase from TextVector //condition dropped at v1.1.4 because of change in EnterLocationNames
18426 /* else */ if(TextHandler->FindText(0, Name, HPos, VPos))
18427  {
18428  if(TextHandler->TextErase(4, HPos, VPos, Name))
18429  {;
18430  } // condition not used
18431  TextFound = true;
18432  }
18433  Utilities->CallLogPop(1956);
18434  return TextFound;
18435 }
18436 
18437 // ---------------------------------------------------------------------------
18438 
18439 void TInterface::AddLocationNameText(int Caller, AnsiString Name, int HPos, int VPos, bool UseEnteredPosition)
18440 {
18441  if(Name == "")
18442  {
18443  return;
18444  }
18445  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",AddLocationNameText," + Name + "," + AnsiString(HPos) + "," +
18446  AnsiString(VPos) + "," + AnsiString((short)UseEnteredPosition));
18447  int VPosHi, VPosLo, TextPosHi, TextPosLo;
18448  TFont *Font = Display->GetFont();
18449 
18450  if(!UseEnteredPosition)
18451  {
18452  if(!Track->FindHighestLowestAndLeftmostNamedElements(0, Name, VPosHi, VPosLo, HPos))
18453  {
18454  Utilities->CallLogPop(1561);
18455  return;
18456  }
18457  int Depth = abs(Font->Height); // Height may be negative - see C++Builder Help file
18458  TextPosHi = VPosHi + 20; // add depth of track element + 4 pixels
18459  TextPosLo = VPosLo - Depth - 4; // reduce by depth of font + 4 pixels
18460  int ScreenPosHi = (Display->DisplayOffsetV * 16) + 576;
18461  int ScreenPosLo = Display->DisplayOffsetV * 16;
18462  if(TextPosLo >= ScreenPosLo)
18463  VPos = TextPosLo; // if Lo value on screen then use that - displays above the location
18464  else if(TextPosHi < ScreenPosHi)
18465  VPos = TextPosHi;
18466  else
18467  VPos = ScreenPosLo + 288; // if location extends to or beyond height of screen the display in centre of screen
18468  }
18469  TTextItem TI(HPos, VPos, Name, Font);
18470 
18471  TI.Font = Font; // may have been changed in constructor when returned as reference
18472  TextHandler->EnterAndDisplayNewText(1, TI, HPos, VPos);
18473  Utilities->CallLogPop(1558);
18474 }
18475 
18476 // ---------------------------------------------------------------------------
18477 
18479 {
18480  try
18481  {
18482 /*
18483  ShowMessage(
18484  "Interface->Left + Interface->Width " + UnicodeString(Interface->Left + Interface->Width) +
18485  "\nInterface->Left + MainScreen->Left + MainScreen->Width " +
18486  UnicodeString(Interface->Left + MainScreen->Left + MainScreen->Width) +
18487  "\n\nMainScreen->Width " + UnicodeString(MainScreen->Width) +
18488  "\nMainScreen->Height " + UnicodeString(MainScreen->Height) +
18489  "\nMainScreen->Top " + UnicodeString(MainScreen->Top) +
18490  "\nMainScreen->Left " + UnicodeString(MainScreen->Left) +
18491  " Right " + UnicodeString(MainScreen->Width + MainScreen->Left) +
18492  "\n\nInterface->Width " + UnicodeString(Interface->Width) +
18493  "\nInterface->Left " + UnicodeString(Interface->Left) +
18494  "\nInterface->Top " + UnicodeString(Interface->Top) +
18495  "\n\nScreenRightButton->Left " + UnicodeString(ScreenRightButton->Left)
18496  );
18497 */
18498 /*
18499  for(unsigned int x=0; x<TrainController->TrainVector.size(); x++)
18500  {
18501  if((TrainController->TrainVectorAt(-1, x).HeadCode == "2K02") && (!TrainController->TrainVectorAt(-1, x).TrainOnContinuation(-1)))
18502  {
18503  TrainController->TrainVectorAt(-1, x).TrainFailurePending = true;
18504  }
18505  }
18506 */
18507 
18508 // throw Exception("Test error"); //generate an error file
18509 
18510 // ShowMessage("MissedTicks = " + AnsiString(MissedTicks) + "; TotalTicks = " + AnsiString(TotalTicks));
18511 
18512  }
18513  catch(const Exception &e)
18514  {
18515  ErrorLog(114, e.Message);
18516  }
18517 }
18518 
18519 // ---------------------------------------------------------------------------
18520 /*
18521  void TInterface::LoadNormalSignalGlyphs(int Caller) //changed - see below
18522  {
18523  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadNormalSignalGlyphs,");
18524  SpeedButton68->Glyph->LoadFromResourceName(0, "gl68"); SpeedButton69->Glyph->LoadFromResourceName(0, "gl69");
18525  SpeedButton70->Glyph->LoadFromResourceName(0, "gl70"); SpeedButton71->Glyph->LoadFromResourceName(0, "gl71");
18526  SpeedButton72->Glyph->LoadFromResourceName(0, "gl72"); SpeedButton73->Glyph->LoadFromResourceName(0, "gl73");
18527  SpeedButton74->Glyph->LoadFromResourceName(0, "gl74"); SpeedButton75->Glyph->LoadFromResourceName(0, "gl75");
18528  Utilities->CallLogPop(**);
18529  }
18530 
18531  //---------------------------------------------------------------------------
18532 
18533  void TInterface::LoadGroundSignalGlyphs(int Caller) //changed - see below
18534  {
18535  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadGroundSignalGlyphs,");
18536  SpeedButton68->Glyph->LoadFromResourceName(0, "bm68grounddblred"); SpeedButton69->Glyph->LoadFromResourceName(0, "bm69grounddblred");
18537  SpeedButton70->Glyph->LoadFromResourceName(0, "bm70grounddblred"); SpeedButton71->Glyph->LoadFromResourceName(0, "bm71grounddblred");
18538  SpeedButton72->Glyph->LoadFromResourceName(0, "bm72grounddblred"); SpeedButton73->Glyph->LoadFromResourceName(0, "gl73grounddblred");
18539  SpeedButton74->Glyph->LoadFromResourceName(0, "gl74grounddblred"); SpeedButton75->Glyph->LoadFromResourceName(0, "bm75grounddblred");
18540  Utilities->CallLogPop(**);
18541  }
18542 */
18543 // ---------------------------------------------------------------------------
18544 void TInterface::LoadNormalSignalGlyphs(int Caller) // changed from the above at v2.3.0 so the signal glyphs change hands
18545 {
18546  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadNormalSignalGlyphs,");
18555  Utilities->CallLogPop(1871);
18556 }
18557 
18558 // ---------------------------------------------------------------------------
18559 
18560 void TInterface::LoadGroundSignalGlyphs(int Caller) // changed from the above at v2.3.0 so the signal glyphs change hands
18561 {
18562  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadGroundSignalGlyphs,");
18571  Utilities->CallLogPop(1872);
18572 }
18573 
18574 // ---------------------------------------------------------------------------
18575 
18576 void TInterface::UpdateOperatorActionPanel(int Caller) // new at v2.2.0
18577  // limit it to 20 entries max
18578 {
18579  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",UpdateOperatorActionPanel");
18581  {
18582  OAListBox->Clear();
18583  }
18585  // new at v2.2.0
18586  {
18587  Utilities->CallLogPop(2092);
18588  return;
18589  }
18590  AnsiString OpTimeToActDisplay;
18591  AnsiString OpTimeToActString;
18592  AnsiString HeadCode;
18593  float OpTimeToActFloat;
18594  TTrainController::THCandTrainPosParam HCandTrainPosParam;
18595 
18598  {
18599  if(OAListBox->Items->Count >= 20)
18600  {
18601  break;
18602  }
18603  OpTimeToActFloat = TrainController->OpTimeToActMultiMapIterator->first;
18604  HCandTrainPosParam = TrainController->OpTimeToActMultiMapIterator->second;
18605  HeadCode = HCandTrainPosParam.first;
18606  if(OpTimeToActFloat < 0.25) // 15 secs estimated
18607  {
18608  OpTimeToActString = "NOW";
18609  }
18610  else if(OpTimeToActFloat < 1)
18611  {
18612  OpTimeToActString = "<1";
18613  }
18614  else
18615  {
18616  OpTimeToActString = AnsiString(floor(OpTimeToActFloat));
18617  }
18618  if(OpTimeToActFloat < 60)
18619  {
18620  OpTimeToActDisplay = HeadCode + AnsiString('\t') + OpTimeToActString;
18621  OAListBox->Items->Add(OpTimeToActDisplay); // original
18622  }
18624  }
18625  Utilities->CallLogPop(2093);
18626 }
18627 
18628 // ---------------------------------------------------------------------------
18629 
18630 void TInterface::LoadUserGraphic(int Caller) // new at v2.4.0
18631 {
18632  try
18633  {
18634  TrainController->LogEvent("LoadUserGraphic");
18635  Utilities->CallLog.push_back(Utilities->TimeStamp() + "," + AnsiString(Caller) + ",LoadUserGraphic");
18636  if(LoadUserGraphicDialog->Execute())
18637  {
18638  TrainController->LogEvent("LoadUserGraphic " + LoadUserGraphicDialog->FileName);
18639  SelectedGraphicFileName = AnsiString(LoadUserGraphicDialog->FileName); // SelectedGraphicFileName is a class member
18641  TTrack::TUserGraphicMap::iterator UGMIt = Track->UserGraphicMap.find(SelectedGraphicFileName);
18642  if(UGMIt == Track->UserGraphicMap.end()) // i.e. there isn't an entry for that filename so insert one, else take no action
18643  {
18644  UGME.first = SelectedGraphicFileName;
18645  TPicture *PicPtr = new TPicture;
18646  PicPtr->LoadFromFile(SelectedGraphicFileName);
18647  UGME.second = PicPtr;
18648  if(!Track->UserGraphicMap.insert(UGME).second) // if no failure then the new entry is inserted
18649  {
18650  throw Exception("Map Insertion Error 1 - UserGraphicMap insertion failure for " + SelectedGraphicFileName);
18651  }
18652  }
18654  SetLevel2TrackMode(65);
18655  }
18656  Utilities->CallLogPop(2191);
18657  }
18658  catch(const EInvalidGraphic &e)
18659  {
18660  ShowMessage(
18661  "Incorrect file format, the file can't be loaded.\nEnsure that the file you want is a valid graphic file with extension .bmp, .gif, .jpg, or .png");
18662  }
18663  catch(const Exception &e)
18664  {
18665  ErrorLog(215, e.Message);
18666  }
18667 }
18668 
18669 // ---------------------------------------------------------------------------
18670 /*
18671  Problems with ifstream reading (see 'SessionFileIntegrityCheck(AnsiString FileName)' above):-
18672 
18673  These problems were with Borland C++Builder 4.
18674 
18675  The functions saved in OldFiles\Backups220809Duringifstream testing were used for testing the odd behaviour where the
18676  ifstream pointer gave different characters using get() and getline(), when reading the timetable entries in the session
18677  file for 20/08/09 at 18:45 (saved). All was well until point 48677 in the session file, when for some reason the
18678  getline(0 & get(0 gave different results. Many earlier timetable strings had been read OK before that, and it wasn't
18679  clear what was special about this particular string.
18680  Later more detailed study found that on reading the string beginning at point 48605 (i.e. the one earlier than above),
18681  within function CheckNoNewLineAtStartNonZeroTerminatedFileString the file pointer (using tellg()) reduced from 48606 to
18682  48604 after reading the 'F' character. Thereafter characters were read correctly but the pointer remained 2 too low.
18683  This is thought to be a flaw in the compiler.
18684  Later again additional tellg()s and a seekg()s were included in CheckNoNewLineAtStartNonZeroTerminatedFileString, and
18685  though these should have had no effect they somehow caused the next getline() within CheckTimetableFromSessionFile to
18686  read a null, even though the pointer had been reset to its value before the call to
18687  CheckNoNewLineAtStartNonZeroTerminatedFileString. Again this seems to be a flaw in the compiler, where the pointer
18688  that is indicated by tellg and the true pointer within the system can be different.
18689  Tried the old c++ stream library to see if that worked but it was exactly the same. Probably because the same code is
18690  used for both with the new library just defined within the std namespace.
18691  Success!! Traced to the putback function failing. It (apparently) can't be used if the file pointer has been altered
18692  after the last read that is to be put back. Corrected that & the most recent session file checked out & loaded OK.
18693  (note - don't need the ifstream file to be open in output mode for the putback to work)
18694  But: the earlier file - 18:45 as above - still fails to advance the file pointer in the middle of checking the
18695  timetable, it sticks at position 48601. This position points to 'r' in 'Frh' just before a newline. Also the file
18696  integrity is OK up to and after this sticking point. Oddly though the loading function works fine (i.e. by bypassing
18697  the integrity check function), though the timetable isn't read directly, it is copied to a new stand-alone timetable
18698  file and that read by the program.
18699  Created a new version of CheckNoNewLineAtStartNonZeroTerminatedFileString with 'New' at end, & got rid of all the
18700  internal digressions & getlines. This passed the earlier sticking point, but stuck later at 48677, i.e. the 'h' from
18701  'Frh' at the end of the entry following that for the earlier sticking point. Here
18702  CheckNoNewLineAtStartNonZeroTerminatedFileStringNew works fine, with end pointer correctly set at 48680, i.e. after the
18703  newline, but the subsequent getline() function, although it retrieves the line correctly, the file pointer is set to
18704  48677, i.e. before the newline, so getline seems to fail to extract the newline character. Still to check - why doesn't
18705  CheckNoNewLineAtStartNonZeroTerminatedFileStringNew see 'h' instead of '0' in the subsequent read? If it did the two
18706  would tally, though would still be wrong.
18707  Further investigation:- CheckNoNewLineAtStartNonZeroTerminatedFileStringNew doesn't seem to recognize the file pointer
18708  as set by seekg at 48677. It continues to read at the point it left off earlier, whereas getline() does read at 48677
18709  & recovers 'h'. Continuing to apply getline() after the above effect it is found that it doesn't extract newlines after
18710  reading further lines, but extracts them when read alone i.e. it reads a line then a null in succession, although the
18711  lines are only separated by single newline characters.
18712 
18713  Need to check:
18714  1. Does the file read correctly if only get() functions used without getline() and without resetting the file pointer?
18715  2. Does the file read correctly if only getline() functions used without get() and without resetting the file pointer?
18716  3. Does the file read correctly if get() functions alternated with getline() but without resetting the file pointer?
18717 
18718  For 1: Still goes wrong at usual place, reads 'h' at the same point. Try not resetting the file pointer with seekg.
18719  Tried this - got past the earlier point but failed later with a reduction in file pointer after a character read. In
18720  fact the reduction was by 40 bytes for reading a single comma! Try without any tellg's - yes, that got past all the
18721  timetable OK. So, works OK with just get() providing no tellg's (& no seekg's).
18722 
18723  For 2: Works OK using getline().
18724 
18725  For 3: Gets to end of timetable OK but the next tellg gives a wrong value. Check if using getline() alone gives a
18726  wrong tellg. Tried getline() alone, reached end of TT as before, but gave the same wrong file pos on using tellg.
18727  Try continuing to see if works OK in spite of tellg giving wrong result. Yes it works OK. Hence the problem seems to
18728  be tellg, which sometimes returns wrong results, and they corrupt things when used in seekg.
18729 
18730  Overall conclusion: Avoid all tellg's & seekg's. If need to reset a file position then close and reopen it.
18731 */
18732 
18733 // ---------------------------------------------------------------------------
18734 
TAllRoutes::TrackIsInARoute
bool TrackIsInARoute(int Caller, int TrackVectorPosition, int LinkPos)
Examines Route2MultiMap and if the element at TrackVectorPosition with LinkPos (can be entry or exit)...
Definition: TrackUnit.cpp:16268
TInterface::SpeedButton59
TSpeedButton * SpeedButton59
Definition: InterfaceUnit.h:563
TInterface::CopyTTEntryButtonClick
void __fastcall CopyTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3624
TInterface::CtrlKey
bool CtrlKey
true when the CTRL key is pressed (see also ShiftKey)
Definition: InterfaceUnit.h:933
TInterface::MTBFEditBox
TEdit * MTBFEditBox
Definition: InterfaceUnit.h:481
TOnePrefDir::LastElementPtr
TPrefDirVectorIterator LastElementPtr(int Caller)
Return a pointer to the last element in the vector.
Definition: TrackUnit.cpp:10384
TInterface::ScreenLeftButtonClick
void __fastcall ScreenLeftButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8389
TInterface::ExitMenuItem
TMenuItem * ExitMenuItem
Definition: InterfaceUnit.h:417
TTrain::AllowedToPassRedSignal
bool AllowedToPassRedSignal
set when train has been called on, or when under signaller control and instructed to pass a red signa...
Definition: TrainUnit.h:339
TInterface::TextMoveVPos
int TextMoveVPos
used to store the original text 'H' & 'V' positions for use during text moving
Definition: InterfaceUnit.h:1098
TInterface::OperMode
@ OperMode
Definition: InterfaceUnit.h:851
TTrain::ZeroPowerNoNewShuttleFromNonRepeatMessage
bool ZeroPowerNoNewShuttleFromNonRepeatMessage
Definition: TrainUnit.h:306
TInterface::SpeedButton140
TSpeedButton * SpeedButton140
Definition: InterfaceUnit.h:644
TTrain::ZeroPowerNoNewServiceMessage
bool ZeroPowerNoNewServiceMessage
Definition: TrainUnit.h:305
TUserGraphicItem::UserGraphic
TPicture * UserGraphic
Definition: DisplayUnit.h:36
TTrack::UserGraphicVectorAt
TUserGraphicItem & UserGraphicVectorAt(int Caller, int At)
A range-checked version of UserGraphicVector.at(At)
Definition: TrackUnit.cpp:10357
TInterface::AddPrefDirButton
TBitBtn * AddPrefDirButton
Definition: InterfaceUnit.h:116
TInterface::RemoveTrainMenuItem
TMenuItem * RemoveTrainMenuItem
Definition: InterfaceUnit.h:467
TInterface::LocationNamesSetImage
TImage * LocationNamesSetImage
Definition: InterfaceUnit.h:278
TInterface::SpeedLimitBox
TEdit * SpeedLimitBox
distance/speed setting edit box that accepts speed limits
Definition: InterfaceUnit.h:92
TTextItem::VPos
int VPos
the vertical position on the railway
Definition: TextUnit.h:50
TInterface::SaveImageAndGridMenuItemClick
void __fastcall SaveImageAndGridMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2602
TDisplay::DisplayOffsetHHome
static int DisplayOffsetHHome
the horizontal offset of the 'Home' display
Definition: DisplayUnit.h:80
TTrainController
Handles all train and timetable activities, only one object created.
Definition: TrainUnit.h:635
TInterface::FloatingInfoMenu
TMenuItem * FloatingInfoMenu
Definition: InterfaceUnit.h:443
TInterface::SpeedButton34
TSpeedButton * SpeedButton34
Definition: InterfaceUnit.h:538
TInterface::NewTTEntryKeyFlag
bool NewTTEntryKeyFlag
Definition: InterfaceUnit.h:1020
TInterface::ConflictAnalysisButtonClick
void __fastcall ConflictAnalysisButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12378
TInterface::CallingOnButton
TSpeedButton * CallingOnButton
Definition: InterfaceUnit.h:205
TInterface::BuildTrainDataVectorForValidateFile
bool BuildTrainDataVectorForValidateFile(int Caller, std::ifstream &TTBLFile, bool GiveMessages, bool CheckLocationsExistInRailway)
Check the integrity of a stored timetable file (either as a stand alone file or within a session file...
Definition: InterfaceUnit.cpp:17045
TInterface::SpeedButton42
TSpeedButton * SpeedButton42
Definition: InterfaceUnit.h:546
TInterface::SelectBitmapMouseLocX
int SelectBitmapMouseLocX
when flag SelectPickedUp is set to true (see above - to allow a selected screen area to move during M...
Definition: InterfaceUnit.h:1074
TInterface::PrefDirPanel
TPanel * PrefDirPanel
'Set preferred directions' panel
Definition: InterfaceUnit.h:359
TInterface::PrefDirPanelLabel
TLabel * PrefDirPanelLabel
label to the left of PrefDirPanel
Definition: InterfaceUnit.h:305
TOnePrefDir::RebuildPrefDirVector
void RebuildPrefDirVector(int Caller)
Called after the track vector has been rebuilt following linking, to rebuild the preferred direction ...
Definition: TrackUnit.cpp:11839
TInterface::MTBFEditBoxKeyUp
void __fastcall MTBFEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:12193
TInterface::TrackMode
@ TrackMode
Definition: InterfaceUnit.h:851
TOneRoute::GetPreferredRouteStartElement
bool GetPreferredRouteStartElement(int Caller, int HLoc, int VLoc, TOnePrefDir *EveryPrefDir, bool ConsecSignalsRoute, bool AutoSigsFlag)
Set the starting conditions for a preferred direction or automatic signal route selection beginning o...
Definition: TrackUnit.cpp:12928
TAllRoutes::LockedRouteVector
TLockedRouteVector LockedRouteVector
the vector that stores all the locked routes on the railway
Definition: TrackUnit.h:1586
TInterface::SaveSessionButton
TBitBtn * SaveSessionButton
Definition: InterfaceUnit.h:201
TInterface::TTLabel2
TLabel * TTLabel2
Definition: InterfaceUnit.h:340
TInterface::TTClockx1ButtonClick
void __fastcall TTClockx1ButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11796
TUtilities::LoadFileString
AnsiString LoadFileString(std::ifstream &InFile)
loads a string value from the file
Definition: Utilities.cpp:182
TInterface::LengthConversionPanel
TPanel * LengthConversionPanel
Definition: InterfaceUnit.h:105
TInterface::SpeedButton143
TSpeedButton * SpeedButton143
Definition: InterfaceUnit.h:647
TInterface::ChangeDirectionMenuItem
TMenuItem * ChangeDirectionMenuItem
Definition: InterfaceUnit.h:462
TTrack::AnyLinkedLevelCrossingElementsWithRoutesOrTrains
bool AnyLinkedLevelCrossingElementsWithRoutesOrTrains(int Caller, int HLoc, int VLoc, bool &TrainPresent)
True if a route or train present on any linked level crossing element.
Definition: TrackUnit.cpp:6713
TTrain::MidEntryPos
int MidEntryPos
Definition: TrainUnit.h:327
TTrainController::RebuildOpTimeToActMultimap
void RebuildOpTimeToActMultimap(int Caller)
new v2.2.0 for OperatorActionPanel
Definition: TrainUnit.cpp:17382
TTrainController::PwrHigh
bool PwrHigh
Definition: TrainUnit.h:743
TInterface::StepForwardMenuItem
TMenuItem * StepForwardMenuItem
Definition: InterfaceUnit.h:465
TTrack::SelectGraphicVector
TUserGraphicVector SelectGraphicVector
Definition: TrackUnit.h:705
TFixedTrackPiece::GraphicPtr
Graphics::TBitmap * GraphicPtr
the track bitmap for display on the zoomed-in railway
Definition: TrackUnit.h:90
SignallerMoveForwards
@ SignallerMoveForwards
Definition: TrainUnit.h:50
TInterface::SignallerControlStopMenuItem
TMenuItem * SignallerControlStopMenuItem
Definition: InterfaceUnit.h:466
TRailGraphics::ConvertSignalsToOppositeHand
void ConvertSignalsToOppositeHand(int Caller)
Converts all signal graphics to opposite hand new at v2.3.0.
Definition: GraphicUnit.cpp:4307
TInterface::FormResize
void __fastcall FormResize(TObject *Sender)
Definition: InterfaceUnit.cpp:12047
TInterface::SpeedButton70
TSpeedButton * SpeedButton70
Definition: InterfaceUnit.h:574
TInterface::SpeedButton144
TSpeedButton * SpeedButton144
Definition: InterfaceUnit.h:648
TInterface::SpeedButton32
TSpeedButton * SpeedButton32
Definition: InterfaceUnit.h:536
TInterface::SaveTTAsButtonClick
void __fastcall SaveTTAsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4093
TInterface::SelectBitmapHLoc
int SelectBitmapHLoc
the original (prior to moving & after finished moving) HLoc value of Edit->Select & Edit->Reselect
Definition: InterfaceUnit.h:1072
TInterface::OperatorActionButton
TBitBtn * OperatorActionButton
Definition: InterfaceUnit.h:202
TInterface::DistanceKey
TImage * DistanceKey
information panel displayed when setting distances & speed limits
Definition: InterfaceUnit.h:268
AboutUnit.h
Arrive
@ Arrive
Definition: TrainUnit.h:49
TInterface::OperatorActionPanelDragStartX
int OperatorActionPanelDragStartX
mouse 'X' position when the OperatorActionPanel begins to be dragged
Definition: InterfaceUnit.h:1060
TInterface::SpeedButton54
TSpeedButton * SpeedButton54
Definition: InterfaceUnit.h:558
TInterface::PasteWarningSentFlag
bool PasteWarningSentFlag
indicates that the warning message about pasting overwriting the area has been given,...
Definition: InterfaceUnit.h:955
TInterface::StartWholeRailwayMoveVPos
int StartWholeRailwayMoveVPos
mouse Y position when start to move the whole railway
Definition: InterfaceUnit.h:1084
TTrain::ZeroPowerNoCDTMessage
bool ZeroPowerNoCDTMessage
Definition: TrainUnit.h:304
TTrain::CallingOnFlag
bool CallingOnFlag
calling on permitted
Definition: TrainUnit.h:345
TInterface::UnrestrictedButton
TBitBtn * UnrestrictedButton
Definition: InterfaceUnit.h:197
TTrack::UserGraphicMap
TUserGraphicMap UserGraphicMap
the map of graphic filenames as key and TPicture* as values
Definition: TrackUnit.h:706
TRailGraphics::SpeedBut72NormBlackGlyph
Graphics::TBitmap * SpeedBut72NormBlackGlyph
Definition: GraphicUnit.h:1048
TOnePrefDir::CheckPrefDirAgainstTrackVector
void CheckPrefDirAgainstTrackVector(int Caller)
Check loaded PrefDir against loaded track, and if discrepancies found give message & clear EveryPrefD...
Definition: TrackUnit.cpp:11879
TInterface::ExportTTMenuItemClick
void __fastcall ExportTTMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3009
TInterface::RestoreTTKeyFlag
bool RestoreTTKeyFlag
Definition: InterfaceUnit.h:1026
TInterface::CancelSelectionMenuItemClick
void __fastcall CancelSelectionMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9663
TRailGraphics::ChangeAllTransparentColours
void ChangeAllTransparentColours(TColor NewTransparentColour, TColor OldTransparentColour)
Definition: GraphicUnit.cpp:3579
TInterface::PERFLOG_DIR_NAME
static const UnicodeString PERFLOG_DIR_NAME
Definition: InterfaceUnit.h:864
TInterface::WholeRailwayMoving
bool WholeRailwayMoving
true when moving the railway with the mouse, new at v2.1.0
Definition: InterfaceUnit.h:1005
TOneRoute::GetNonPreferredRouteStartElement
bool GetNonPreferredRouteStartElement(int Caller, int HLoc, int VLoc, bool ConsecSignalsRoute, bool Callon)
Set the starting conditions for a non-preferred (i.e. unrestricted) route selection beginning on HLoc...
Definition: TrackUnit.cpp:14343
TInterface::TextFoundFlag
bool TextFoundFlag
indicates that a text item has been found when clicking on a build screen during 'AddText' or 'MoveTe...
Definition: InterfaceUnit.h:985
TInterface::DisableRouteButtons
void DisableRouteButtons(int Caller)
Called during operation whenever the route type buttons need to be disabled, e.g. when paused.
Definition: InterfaceUnit.cpp:17789
TInterface::OperateRailwayMenuItemClick
void __fastcall OperateRailwayMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2013
TInterface::DerailImage
TImage * DerailImage
Definition: InterfaceUnit.h:264
TTrain::MaxRunningSpeed
double MaxRunningSpeed
the current maximum train running speed
Definition: TrainUnit.h:385
TInterface::TTLabel3
TLabel * TTLabel3
Definition: InterfaceUnit.h:341
TTrack::BarriersDownVector
TActiveLCVector BarriersDownVector
vector of LCs with barriers down
Definition: TrackUnit.h:689
TPrefDirElement::GetXLinkPos
int GetXLinkPos() const
Returns the XLink array position.
Definition: TrackUnit.h:289
TRailGraphics::SpeedBut75NormBlackGlyph
Graphics::TBitmap * SpeedBut75NormBlackGlyph
Definition: GraphicUnit.h:1051
TTrack::IsLCBarrierDownAtHV
bool IsLCBarrierDownAtHV(int Caller, int HLoc, int VLoc)
True if an open (to trains) level crossing is found at H & V.
Definition: TrackUnit.cpp:6566
RestoreTimetableControl
@ RestoreTimetableControl
Definition: TrainUnit.h:50
TTrainController::LastSessionSaveTTClockTime
TDateTime LastSessionSaveTTClockTime
Definition: TrainUnit.h:646
TInterface::TTSelectedEntry
AnsiString TTSelectedEntry
used to record the current timetable entry when changing to AZ order or back to original order
Definition: InterfaceUnit.h:920
TUtilities::ScreenElementWidth
int ScreenElementWidth
width of display screen in elements
Definition: Utilities.h:48
TAllRoutes::AutoSigsRoute
@ AutoSigsRoute
Definition: TrackUnit.h:1516
TInterface::SpeedButton19
TSpeedButton * SpeedButton19
Definition: InterfaceUnit.h:523
TTrack::GetVectorPositionFromTrackMap
int GetVectorPositionFromTrackMap(int Caller, int HLoc, int VLoc, bool &FoundFlag)
Returns the track vector position corresponding to the Hloc & VLoc positions, FoundFlag indicates whe...
Definition: TrackUnit.cpp:5079
TTrack::GetTrackElementFromTrackMap
TTrackElement & GetTrackElementFromTrackMap(int Caller, int HLoc, int VLoc)
Return a reference to the element at HLoc & VLoc, if no element is found an error is thrown.
Definition: TrackUnit.cpp:5106
TActionVectorEntry::LocationType
TTimetableLocationType LocationType
indicates where the train is when the relevant action occurs
Definition: TrainUnit.h:112
TInterface::MasterClockTimer
void __fastcall MasterClockTimer(TObject *Sender)
Definition: InterfaceUnit.cpp:7698
TTrack::GapFlashGreenPosition
int GapFlashGreenPosition
Definition: TrackUnit.h:673
TInterface::MainScreen
TImage * MainScreen
the railway display screen
Definition: InterfaceUnit.h:285
TInterface::SpeedButton67
TSpeedButton * SpeedButton67
Definition: InterfaceUnit.h:571
NamedNonStationLocation
@ NamedNonStationLocation
Definition: TrackUnit.h:64
TInterface::CutMenuItem
TMenuItem * CutMenuItem
Definition: InterfaceUnit.h:432
TInterface::SpeedButton120
TSpeedButton * SpeedButton120
Definition: InterfaceUnit.h:624
TInterface::LCResetCounter
unsigned int LCResetCounter
count up to 20 then resets - to check LCs & raise barriers if no route & no train present
Definition: InterfaceUnit.h:1046
TInterface::BlueBgndMenuItem
TMenuItem * BlueBgndMenuItem
Definition: InterfaceUnit.h:427
TTrack::NoActiveTrack
bool NoActiveTrack(int Caller)
True if there is no active track in the railway.
Definition: TrackUnit.cpp:1645
TInterface::TTLabel1
TLabel * TTLabel1
Definition: InterfaceUnit.h:339
TTrack::CalcHLocMinEtc
void CalcHLocMinEtc(int Caller)
Examine TrackVector, InactiveTrackVector and TextVector, and set the values that indicate the extent ...
Definition: TrackUnit.cpp:9356
TInterface::ResetChangedFileDataAndCaption
void ResetChangedFileDataAndCaption(int Caller, bool NonPrefDirChangesMade)
Called whenever the railway is changed to deal with title displays (loaded railway and timetable) and...
Definition: InterfaceUnit.cpp:15893
TTrain::MaxBrakeRate
double MaxBrakeRate
the maximum brake rate that the train can achieve
Definition: TrainUnit.h:389
TInterface::SpeedButton52
TSpeedButton * SpeedButton52
Definition: InterfaceUnit.h:556
TInterface::IMAGE_DIR_NAME
static const UnicodeString IMAGE_DIR_NAME
Definition: InterfaceUnit.h:866
TInterface::ShowPerformancePanel
bool ShowPerformancePanel
true when the 'show performance panel' button has been clicked during operation
Definition: InterfaceUnit.h:979
TInterface::LoadSessionDialog
TOpenDialog * LoadSessionDialog
Definition: InterfaceUnit.h:489
TTextHandler::TextVector
TTextVector TextVector
Definition: TextUnit.h:69
TInterface::OutputLog10MouseDown
void __fastcall OutputLog10MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11168
TTrack::Lowering
@ Lowering
Definition: TrackUnit.h:523
TTrack::FindNonPlatformMatch
bool FindNonPlatformMatch(int Caller, int HLoc, int VLoc, int &Position, TTrackElement &TrackElement)
True if find a non-platform element at HLoc & VLoc, and if so return its TrackVector position and a r...
Definition: TrackUnit.cpp:2449
TInterface::SpeedButton116
TSpeedButton * SpeedButton116
Definition: InterfaceUnit.h:620
TTrack::MatchingPoint
bool MatchingPoint(int Caller, unsigned int TrackVectorPosition, unsigned int DivergingPosition)
Definition: TrackUnit.cpp:5235
TTrackElement::StationEntryStopLinkPos2
int StationEntryStopLinkPos2
Used for track at platforms and non-station named locations to mark the train front element stop posi...
Definition: TrackUnit.h:149
TTrain::MidExitPos
int MidExitPos
Definition: TrainUnit.h:327
TInterface::NewSelectBitmapVLoc
int NewSelectBitmapVLoc
as above for VLoc
Definition: InterfaceUnit.h:1058
TInterface::MoveTextOrGraphic
@ MoveTextOrGraphic
Definition: InterfaceUnit.h:881
TInterface::ScreenGridButton
TBitBtn * ScreenGridButton
Definition: InterfaceUnit.h:72
TTrack::EnterLocationName
void EnterLocationName(int Caller, AnsiString LocationName, bool AddingElements)
All platform, concourse, footcrossing & non-station named location elements are able to have a Locati...
Definition: TrackUnit.cpp:7356
TInterface::EditMenu
TMenuItem * EditMenu
Definition: InterfaceUnit.h:429
TTrain::TrainFailed
bool TrainFailed
added at v2.4.0 to indicate failure
Definition: TrainUnit.h:371
TUtilities::CheckFileStringZeroDelimiter
bool CheckFileStringZeroDelimiter(std::ifstream &InFile)
checks that the value is a string ('0' only accepted as the delimiter), returns true for success
Definition: Utilities.cpp:384
DisplayUnit.h
TInterface::ResetSelectRect
void ResetSelectRect()
SelectRect is the rectangle selected via the 'Edit'menu, and this function sets left,...
Definition: InterfaceUnit.cpp:18410
TInterface::TTClockAdjustWarningHide
bool TTClockAdjustWarningHide
true if user opts not to show the timetable clock adjustment warning (false on starting the program)
Definition: InterfaceUnit.h:987
TInterface::TTLabel9
TLabel * TTLabel9
Definition: InterfaceUnit.h:347
TTrain::ZeroPowerNoFrontSplitMessage
bool ZeroPowerNoFrontSplitMessage
Definition: TrainUnit.h:300
TTrainController::SPADWarning
bool SPADWarning
Definition: TrainUnit.h:729
TInterface::TTClockAdjustCheckBox
TCheckBox * TTClockAdjustCheckBox
Definition: InterfaceUnit.h:229
TOnePrefDir::SavePrefDirVector
void SavePrefDirVector(int Caller, std::ofstream &VecFile)
Save the preferred direction vector to a file.
Definition: TrackUnit.cpp:11636
TInterface::TrackNotLinkedImage
TImage * TrackNotLinkedImage
Definition: InterfaceUnit.h:275
TTrain::DepartureTimeSet
bool DepartureTimeSet
set when stopped at a location and the next action is departure (set in UpdateTrain when ReleaseTime ...
Definition: TrainUnit.h:347
TInterface::WarningHover
bool WarningHover
true when mouse hovers over warning messages during operation - to prevent clicking while changing
Definition: InterfaceUnit.h:1003
TTrack::GetTrackLocsFromScreenPos
void GetTrackLocsFromScreenPos(int Caller, int &HLoc, int &VLoc, int ScreenPosH, int ScreenPosV)
Converse of GetScreenPositionsFromTruePos except that in this function HLoc & VLoc are expressed in t...
Definition: TrackUnit.cpp:6859
TInterface::SaveTTAsButton
TButton * SaveTTAsButton
Definition: InterfaceUnit.h:146
TInterface::ZoomButtonClick
void __fastcall ZoomButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8626
TInterface::SpeedButton90
TSpeedButton * SpeedButton90
Definition: InterfaceUnit.h:594
TTrain::LagElement
int LagElement
Definition: TrainUnit.h:327
TTrack::GetLocationName
AnsiString GetLocationName(unsigned int InactiveTrackVectorPosition)
Return location name for a given inactive track vector position.
Definition: TrackUnit.h:720
TTrainController::BufferAttentionWarning
bool BufferAttentionWarning
Definition: TrainUnit.h:729
TInterface::ExitTrackButtonClick
void __fastcall ExitTrackButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1705
TTrainController::TrainVectorAtIdent
TTrain & TrainVectorAtIdent(int Caller, int TrainID)
Return a reference to the train with ID TrainID, carries out validity checking on TrainID.
Definition: TrainUnit.cpp:8653
TInterface::SpeedButton135
TSpeedButton * SpeedButton135
Definition: InterfaceUnit.h:639
TInterface::SpeedButton111
TSpeedButton * SpeedButton111
Definition: InterfaceUnit.h:615
TInterface::RouteCancelFlag
bool RouteCancelFlag
true when route cancel button pressed, enables a right mouse click to cancel a route if in an appropr...
Definition: InterfaceUnit.h:965
TTextHandler::LoadText
void LoadText(int Caller, std::ifstream &VecFile)
load the railway's text from VecFile
Definition: TextUnit.cpp:281
TInterface::SpeedToggleButton2Click
void __fastcall SpeedToggleButton2Click(TObject *Sender)
Definition: InterfaceUnit.cpp:11321
TOnePrefDir::GetStartAndEndPrefDirElements
bool GetStartAndEndPrefDirElements(int Caller, TPrefDirElement &StartElement, TPrefDirElement &EndElement, int &LastIteratorValue)
Called when searching for start and end PrefDirElements when setting up automatic signals routes in P...
Definition: TrackUnit.cpp:12729
TTextItem::HPos
int HPos
the horizontal position on the railway
Definition: TextUnit.h:48
TTrainController::StopTTClockMessage
void StopTTClockMessage(int Caller, AnsiString Message)
sends a message to the user and stops the timetable clock while it is displayed
Definition: TrainUnit.cpp:14030
TInterface::LoadNormalSignalGlyphs
void LoadNormalSignalGlyphs(int Caller)
In trackbuild display normal signal types on signal buttons.
Definition: InterfaceUnit.cpp:18544
TInterface::MainScreenMouseDown3
void MainScreenMouseDown3(int Caller, TMouseButton Button, TShiftState Shift, int X, int Y)
Called when mouse button clicked in zoom-out mode.
Definition: InterfaceUnit.cpp:7055
TInterface::TTLabel11
TLabel * TTLabel11
Definition: InterfaceUnit.h:348
TInterface::CancelTTEntryButton
TButton * CancelTTEntryButton
Definition: InterfaceUnit.h:137
TInterface::SpeedButton8
TSpeedButton * SpeedButton8
Definition: InterfaceUnit.h:512
TInterface::UserGraphicVectorNumber
int UserGraphicVectorNumber
used to store a single item of user graphics
Definition: InterfaceUnit.h:1100
TInterface::PreviousTTEntryButton
TButton * PreviousTTEntryButton
Definition: InterfaceUnit.h:128
TInterface::TrackElementPanel
TPanel * TrackElementPanel
panel containing the track/location/parapet element buttons
Definition: InterfaceUnit.h:376
TAllRoutes::RemoveRouteElement
void RemoveRouteElement(int Caller, int HLoc, int VLoc, int ELink)
Erases the route element from Route2MultiMap and from the PrefDirVector.
Definition: TrackUnit.cpp:17065
TInterface::SelectionValid
bool SelectionValid
true when an area of screen has been selected via the 'Edit' & 'Select' or 'Reselect' menu items
Definition: InterfaceUnit.h:971
TDisplay::InvertElement
void InvertElement(int Caller, int HPos, int VPos)
Definition: DisplayUnit.cpp:140
TInterface::OperateButtonClick
void __fastcall OperateButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2032
TInterface::WhiteBgndMenuItem
TMenuItem * WhiteBgndMenuItem
Definition: InterfaceUnit.h:425
TInterface::ContinuationAutoSignals
void ContinuationAutoSignals(int Caller, TDateTime Now)
Deal with signal resetting on auto signal routes that extend to continuations where trains have depar...
Definition: InterfaceUnit.cpp:14312
TTrainController::CrashWarning
bool CrashWarning
Definition: TrainUnit.h:729
TInterface::LoadInterface
void LoadInterface(int Caller, std::ifstream &SessionFile)
Load the interface part of a session file.
Definition: InterfaceUnit.cpp:16329
TInterface::SpeedButton2
TSpeedButton * SpeedButton2
Definition: InterfaceUnit.h:506
TTrain::PlotTrain
void PlotTrain(int Caller, TDisplay *Disp)
Plots the train on the display in normal (zoomed-in) mode.
Definition: TrainUnit.cpp:7614
TInterface::AutoSigsFlag
bool AutoSigsFlag
true when AutoSig route building selected during operation
Definition: InterfaceUnit.h:927
TInterface::SetRouteButtonsInfoCaptionAndRouteNotStarted
void SetRouteButtonsInfoCaptionAndRouteNotStarted(int Caller)
Enables or disables the route type buttons depending on the route mode, sets the information panel me...
Definition: InterfaceUnit.cpp:17699
TInterface::MoveForwardsMenuItem
TMenuItem * MoveForwardsMenuItem
Definition: InterfaceUnit.h:463
TInterface::YardEdit
TEdit * YardEdit
Definition: InterfaceUnit.h:100
TTrack::CheckActiveLCVector
bool CheckActiveLCVector(int Caller, std::ifstream &VecFile)
Definition: TrackUnit.cpp:3264
TTrack::FindSetAndDisplayMatchingGap
bool FindSetAndDisplayMatchingGap(int Caller, int HLoc, int VLoc)
True if find an unset gap that matches the gap at HLoc & VLoc, if find one mark it with a green circl...
Definition: TrackUnit.cpp:4005
TInterface::Paused
@ Paused
Definition: InterfaceUnit.h:873
TTrainController::SaveSessionTrains
void SaveSessionTrains(int Caller, std::ofstream &SessionFile)
save trains to a session file
Definition: TrainUnit.cpp:14045
TInterface::SpeedButton41
TSpeedButton * SpeedButton41
Definition: InterfaceUnit.h:545
TInterface::TrackInfoMenuItem
TMenuItem * TrackInfoMenuItem
Definition: InterfaceUnit.h:444
TRailGraphics::SpeedBut73NormBlackGlyph
Graphics::TBitmap * SpeedBut73NormBlackGlyph
Definition: GraphicUnit.h:1049
TInterface::Operating
@ Operating
Definition: InterfaceUnit.h:873
TTextHandler
A single object that handles text management.
Definition: TextUnit.h:62
TInterface::EditTimetableMenuItemClick
void __fastcall EditTimetableMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3163
TInterface::TakeSignallerControlMenuItemClick
void __fastcall TakeSignallerControlMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9751
TInterface::TimetableMode
@ TimetableMode
Definition: InterfaceUnit.h:851
TInterface::ScreenUpButtonClick
void __fastcall ScreenUpButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8567
TInterface::ShowHideTTButtonClick
void __fastcall ShowHideTTButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3340
TInterface::ImageMenu
TMenuItem * ImageMenu
Definition: InterfaceUnit.h:450
TInterface::LoadGroundSignalGlyphs
void LoadGroundSignalGlyphs(int Caller)
In trackbuild display ground signal types on signal buttons.
Definition: InterfaceUnit.cpp:18560
TUtilities::LoadFileDouble
double LoadFileDouble(std::ifstream &InFile)
loads a double value from the file (converts from a string to a double) and uses the local decimal po...
Definition: Utilities.cpp:164
TInterface::CPArrivalsCheckBox
TCheckBox * CPArrivalsCheckBox
Definition: InterfaceUnit.h:242
TInterface::OneEntryTimetableMemo
TMemo * OneEntryTimetableMemo
the single service editing and display area on the right hand side of the timetable edit screen
Definition: InterfaceUnit.h:397
TInterface::SelectBitmapVLoc
int SelectBitmapVLoc
the original (prior to moving & after finished moving) VLoc value of Edit->Select & Edit->Reselect
Definition: InterfaceUnit.h:1078
TInterface::LengthOKButtonClick
void __fastcall LengthOKButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1360
TInterface::SpeedButton47
TSpeedButton * SpeedButton47
Definition: InterfaceUnit.h:551
TInterface::OutputLog1MouseDown
void __fastcall OutputLog1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11080
NotStarted
@ NotStarted
Definition: TrainUnit.h:80
TTrack::ShowSelectedGap
void ShowSelectedGap(int Caller, TDisplay *Disp)
Called during gap setting to mark a gap with a red circle - after which the program awaits user selec...
Definition: TrackUnit.cpp:4164
TInterface::AppDeactivate
void __fastcall AppDeactivate(TObject *Sender)
Definition: InterfaceUnit.cpp:758
TInterface::UnrestrictedButtonClick
void __fastcall UnrestrictedButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2125
TInterface::ExportTTMenuItem
TMenuItem * ExportTTMenuItem
Definition: InterfaceUnit.h:415
TInterface::SaveTTKeyFlag
bool SaveTTKeyFlag
Definition: InterfaceUnit.h:1024
TRailGraphics::SpeedBut71NormBlackGlyph
Graphics::TBitmap * SpeedBut71NormBlackGlyph
Definition: GraphicUnit.h:1047
TInterface::SelectNewGraphicClick
void __fastcall SelectNewGraphicClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12340
TInterface::SpeedButtonClick
void __fastcall SpeedButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:883
TTrack::GetHLocMax
int GetHLocMax()
Definition: TrackUnit.h:770
TTrack::CheckUserGraphics
bool CheckUserGraphics(int Caller, std::ifstream &InFile, UnicodeString GraphicsPath)
checks all user graphics & returns true for success
Definition: TrackUnit.cpp:3140
TInterface::CPEditArrRange
TEdit * CPEditArrRange
Definition: InterfaceUnit.h:245
TInterface::ErrorButtonClick
void __fastcall ErrorButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10480
TTrainController::SPADEvents
int SPADEvents
Definition: TrainUnit.h:776
TInterface::PasteTTEntryButton
TButton * PasteTTEntryButton
Definition: InterfaceUnit.h:132
TInterface::SpeedButton139
TSpeedButton * SpeedButton139
Definition: InterfaceUnit.h:643
TInterface::SpeedButton3
TSpeedButton * SpeedButton3
Definition: InterfaceUnit.h:507
TTrain::ZeroPowerNoRepeatShuttleMessage
bool ZeroPowerNoRepeatShuttleMessage
Definition: TrainUnit.h:307
TTrackElement::SigAspect
enum TTrackElement::@1 SigAspect
TInterface::SetLevel2PrefDirMode
void SetLevel2PrefDirMode(int Caller)
Sets the Level2PrefDirMode user mode, using the Level2PrefDirMode variable to determine the mode.
Definition: InterfaceUnit.cpp:14041
TInterface::SetGapsButton
TBitBtn * SetGapsButton
Definition: InterfaceUnit.h:64
TTrain::ActionVectorEntryPtr
TActionVectorEntry * ActionVectorEntryPtr
points to the current position in the ActionVector (a member of the TTrainDataEntry class)
Definition: TrainUnit.h:335
TTrainDataEntry
Contains all data for a single train.
Definition: TrainUnit.h:177
clSignalStopBackground
#define clSignalStopBackground
Definition: GraphicUnit.h:299
TTrainController::LateDeps
int LateDeps
Definition: TrainUnit.h:769
TAllRoutes::IsElementInLockedRouteGetPrefDirElementGetLockedVectorNumber
bool IsElementInLockedRouteGetPrefDirElementGetLockedVectorNumber(int Caller, int TrackVectorPosition, int XLinkPos, TPrefDirElement &PrefDirElement, int &LockedVectorNumber)
Checks whether the preferred direction element at TrackVectorPosition with XLinkPos value is in a loc...
Definition: TrackUnit.cpp:17517
TInterface::ExitMenuItemClick
void __fastcall ExitMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:5390
TrackUnit.h
TInterface::SpeedButton29
TSpeedButton * SpeedButton29
Definition: InterfaceUnit.h:533
TInterface::SpeedButton35
TSpeedButton * SpeedButton35
Definition: InterfaceUnit.h:539
TInterface::ScreenDownButtonClick
void __fastcall ScreenDownButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8507
TAllRoutes::CheckRoutes
bool CheckRoutes(int Caller, int NumberOfActiveElements, std::ifstream &InFile)
Performs an integrity check on the routes stored in a session file and returns false if there is an e...
Definition: TrackUnit.cpp:17708
TTrack::LengthMarker
void LengthMarker(int Caller, TDisplay *Disp)
Examine all elements in the TrackVector and if have a valid length mark the relevant track using Mark...
Definition: TrackUnit.cpp:8698
TDisplay::ClearDisplay
void ClearDisplay(int Caller)
Empty the display.
Definition: DisplayUnit.cpp:181
TDisplay::Top
int Top()
Return the top pixel position of the screen.
Definition: DisplayUnit.h:120
TInterface::ExitPrefDirButtonClick
void __fastcall ExitPrefDirButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1994
TInterface::SaveErrorFile
void SaveErrorFile()
Save the error log after an error has been thrown - no need for a caller.
Definition: InterfaceUnit.cpp:17801
TTrain::SendMissedActionLogs
void SendMissedActionLogs(int Caller, int IncNum, TActionVectorEntry *Ptr)
Missed actions (see NameInTimetableBeforeCDT above) sent to the performance log and performance file.
Definition: TrainUnit.cpp:5856
TInterface::SpeedVariableLabel2
TLabel * SpeedVariableLabel2
Definition: InterfaceUnit.h:113
TInterface::TrainInfoMenuItem
TMenuItem * TrainInfoMenuItem
Definition: InterfaceUnit.h:446
TOneRoute::RouteID
int RouteID
the ID number of the route, this is needed for session saves
Definition: TrackUnit.h:1409
TAllRoutes
Handles data and functions relating to all routes on the railway.
Definition: TrackUnit.h:1495
TInterface::TrainStatusInfoOnOffMenuItemClick
void __fastcall TrainStatusInfoOnOffMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:5454
TInterface::ConverttoRightHandSignalsMenuItem
TMenuItem * ConverttoRightHandSignalsMenuItem
Definition: InterfaceUnit.h:468
TInterface::SpeedButton96
TSpeedButton * SpeedButton96
Definition: InterfaceUnit.h:600
TInterface::TTClockxHalfButtonClick
void __fastcall TTClockxHalfButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11815
TInterface::OutputLog3
TLabel * OutputLog3
Definition: InterfaceUnit.h:294
TUserGraphicItem::VPos
int VPos
Definition: DisplayUnit.h:34
TOnePrefDir::ExternalStorePrefDirElement
void ExternalStorePrefDirElement(int Caller, TPrefDirElement LoadPrefDirElement)
Store a single pref dir element in the vector & map - used by other classes.
Definition: TrackUnit.h:1324
clB5G5R4
#define clB5G5R4
Definition: GraphicUnit.h:285
Utilities.h
TTrainController::TContinuationAutoSigVectorIterator
TContinuationAutoSigVector::iterator TContinuationAutoSigVectorIterator
Definition: TrainUnit.h:665
TInterface::SaveImageNoGridMenuItemClick
void __fastcall SaveImageNoGridMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2510
TInterface::SpeedButton25
TSpeedButton * SpeedButton25
Definition: InterfaceUnit.h:529
TInterface::HelpMenu
TMenuItem * HelpMenu
Definition: InterfaceUnit.h:456
TInterface::TrackOKButtonClick
void __fastcall TrackOKButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:960
TTrainController::CheckSessionLockedRoutes
bool CheckSessionLockedRoutes(int Caller, std::ifstream &SessionFile)
Part of the session file integrity check for locked routes, true for success.
Definition: TrainUnit.cpp:14149
TTrack::SaveTrack
void SaveTrack(int Caller, std::ofstream &VecFile, bool GraphicsFollow)
Save all active and inactive track elements to VecFile.
Definition: TrackUnit.cpp:2868
TInterface::GapsSetImage
TImage * GapsSetImage
Definition: InterfaceUnit.h:276
TDisplay::Update
void Update()
Repaint the screen display.
Definition: DisplayUnit.h:221
TUserGraphicItem::HPos
int HPos
Definition: DisplayUnit.h:34
TInterface::LocationNameComboBoxKeyUp
void __fastcall LocationNameComboBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:4662
TTrainController::CreateTTAnalysisFile
bool CreateTTAnalysisFile(int Caller, AnsiString RailwayTitle, AnsiString TimetableTitle, AnsiString CurDir, bool ArrChecked, bool DepChecked, bool AtLocChecked, int ArrRange, int DepRange)
Generate a timetable analysis file in the 'Formatted Timetables' folder, return false if failed for a...
Definition: TrainUnit.cpp:14991
TInterface::RevertToOriginalRouteSelector
void RevertToOriginalRouteSelector(int Caller)
Clears any route start markers, enables or disables the route cancel button, and resets the informati...
Definition: InterfaceUnit.cpp:12948
TInterface::FileIntegrityCheck
bool FileIntegrityCheck(int Caller, char *FileName) const
Check integrity of a railway file prior to loading, return true for success.
Definition: InterfaceUnit.cpp:12795
TInterface::TTLastServicePtr
TTEVPtr TTLastServicePtr
timetable entry value pointers used during timetable editing
Definition: InterfaceUnit.h:1141
TTrainController::CheckSessionTrains
bool CheckSessionTrains(int Caller, std::ifstream &InFile)
Part of the session file integrity check for train entries, true for success.
Definition: TrainUnit.cpp:14087
TInterface::SpeedButton126
TSpeedButton * SpeedButton126
Definition: InterfaceUnit.h:630
TakeSignallerControl
@ TakeSignallerControl
Definition: TrainUnit.h:49
TOnePrefDir::EraseFromPrefDirVectorAnd4MultiMap
void EraseFromPrefDirVectorAnd4MultiMap(int Caller, int HLoc, int VLoc)
Erase element at HLoc and VLoc from the PrefDirVector and from the 4MultiMap. Note that this entails ...
Definition: TrackUnit.cpp:11702
Simple
@ Simple
Definition: TrackUnit.h:63
TTrack::GapFlashGreen
TGraphicElement * GapFlashGreen
Definition: TrackUnit.h:693
TTrain::ZeroPowerNoRepeatShuttleOrNewServiceMessage
bool ZeroPowerNoRepeatShuttleOrNewServiceMessage
flags to indicate whether the respective message has been sent
Definition: TrainUnit.h:308
TUtilities::RHSignalFlag
bool RHSignalFlag
new at v2.3.0 false=LH signals
Definition: Utilities.h:40
TInterface::SetInitialTrackModeEditMenu
void SetInitialTrackModeEditMenu()
Enables or disables the initial Edit mode submenu items in Track mode.
Definition: InterfaceUnit.cpp:18333
TInterface::DeleteMenuItem
TMenuItem * DeleteMenuItem
Definition: InterfaceUnit.h:438
TTrack::NumberOfGaps
int NumberOfGaps(int Caller)
Returns the number of gaps in the railway.
Definition: TrackUnit.cpp:2496
TInterface::TTClockAdjustOKButtonClick
void __fastcall TTClockAdjustOKButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12357
TInterface::ChangeDirectionMenuItemClick
void __fastcall ChangeDirectionMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9942
TInterface::PointsFlashDuration
float PointsFlashDuration
duration of the flash period when changing points manually
Definition: InterfaceUnit.h:1035
TInterface::LocationNameComboBoxClick
void __fastcall LocationNameComboBoxClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4591
TInterface::TTServiceSyntaxCheckKeyFlag
bool TTServiceSyntaxCheckKeyFlag
Definition: InterfaceUnit.h:1022
TInterface::TLevel2OperMode
TLevel2OperMode
Definition: InterfaceUnit.h:872
TInterface::ConsecSignalsRoute
bool ConsecSignalsRoute
true when AutoSig or preferred route building selected during operation (always same state as Preferr...
Definition: InterfaceUnit.h:929
TOnePrefDir::CheckPrefDirAgainstTrackVectorNoMessage
bool CheckPrefDirAgainstTrackVectorNoMessage(int Caller)
Check loaded PrefDir against loaded track, and if discrepancies found clear EveryPrefDir & PrefDir4Mu...
Definition: TrackUnit.cpp:11930
TTrack::GetVectorPositionsFromInactiveTrackMap
TIMPair GetVectorPositionsFromInactiveTrackMap(int Caller, int HLoc, int VLoc, bool &FoundFlag)
Similar to GetVectorPositionFromTrackMap but for inactive elements, a pair is returned because there ...
Definition: TrackUnit.cpp:5195
TTrain::BackgroundColour
TColor BackgroundColour
the background colour of the train's headcode graphics
Definition: TrainUnit.h:455
TInterface::LengthCancelButtonClick
void __fastcall LengthCancelButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1542
TTrain
Definition: TrainUnit.h:271
TInterface::OutputLog5
TLabel * OutputLog5
Definition: InterfaceUnit.h:296
TTrainController::CheckTimeValidity
bool CheckTimeValidity(int Caller, AnsiString TimeStr, TDateTime &Time)
returns true if the time complies with requirements
Definition: TrainUnit.cpp:9788
clSignallerStopped
#define clSignallerStopped
Definition: GraphicUnit.h:298
TTextHandler::SelectTextVector
TTextVector SelectTextVector
Definition: TextUnit.h:69
TTrackElement::TrainIDOnBridgeTrackPos23
int TrainIDOnBridgeTrackPos23
Set to the TrainID value when a train is present on the element, bridges can have two trains present ...
Definition: TrackUnit.h:151
TOnePrefDir::GetFixedPrefDirElementAt
const TPrefDirElement & GetFixedPrefDirElementAt(int Caller, int At) const
Return a non-modifiable element at PrefDirVector position 'At'.
Definition: TrackUnit.cpp:10398
TInterface::CallOnImage
TImage * CallOnImage
Definition: InterfaceUnit.h:262
TInterface::PerformancePanelDragStartY
int PerformancePanelDragStartY
as above for 'Y'
Definition: InterfaceUnit.h:1069
TInterface::LocationNameTextBox
TEdit * LocationNameTextBox
edit box that accepts location names
Definition: InterfaceUnit.h:94
TTrack::PlotLoweredLinkedLevelCrossingBarriers
void PlotLoweredLinkedLevelCrossingBarriers(int Caller, int BaseElementSpeedTag, int HLoc, int VLoc, int ConsecSignals, TDisplay *Disp, bool Manual)
Plot & open (to trains) all level crossings linked to TrackElement (Manual true = manually lowered,...
Definition: TrackUnit.cpp:5765
TTrack::TActiveLevelCrossing::VLoc
int VLoc
VLoc value for found level crossing element.
Definition: TrackUnit.h:542
TInterface::SaveSessionFlag
bool SaveSessionFlag
true when a session save command has been given - implemented at next clock tick
Definition: InterfaceUnit.h:967
TTrainController::ContinuationTrainExpectationMultiMap
TContinuationTrainExpectationMultiMap ContinuationTrainExpectationMultiMap
Multimap for TContinuationTrainExpectationEntry objects, the access key is the expectation time.
Definition: TrainUnit.h:799
TTrack::GetTruePositionsFromScreenPos
void GetTruePositionsFromScreenPos(int Caller, int &HPos, int &VPos, int ScreenPosH, int ScreenPosV)
Converse of GetScreenPositionsFromTruePos.
Definition: TrackUnit.cpp:6874
TInterface::SpeedButton73
TSpeedButton * SpeedButton73
Definition: InterfaceUnit.h:577
TInterface::TTLabel4
TLabel * TTLabel4
Definition: InterfaceUnit.h:342
TTrain::StoppedForTrainInFront
bool StoppedForTrainInFront
Definition: TrainUnit.h:432
TInterface::ConflictAnalysisKeyFlag
bool ConflictAnalysisKeyFlag
Definition: InterfaceUnit.h:1028
GapJump
@ GapJump
Definition: TrackUnit.h:63
TInterface::Level2OperMode
enum TInterface::TLevel2OperMode Level2OperMode
TInterface::SigsOnRightImage1
TImage * SigsOnRightImage1
Definition: InterfaceUnit.h:282
TInterface::SaveRailwayPDPButton
TBitBtn * SaveRailwayPDPButton
Save button on PrefDirPanel.
Definition: InterfaceUnit.h:119
TInterface::SpeedButton62
TSpeedButton * SpeedButton62
Definition: InterfaceUnit.h:566
TInterface::SpeedButton58
TSpeedButton * SpeedButton58
Definition: InterfaceUnit.h:562
TTrainController::MissedStops
int MissedStops
Definition: TrainUnit.h:771
TInterface::TempTTFileName
AnsiString TempTTFileName
the name for the temporary file used to save loaded timetables for storage in session files & error l...
Definition: InterfaceUnit.h:918
TInterface::PrefDirMode
@ PrefDirMode
Definition: InterfaceUnit.h:851
TInterface::PassRedSignalMenuItem
TMenuItem * PassRedSignalMenuItem
Definition: InterfaceUnit.h:464
TTrackElement::Length01
int Length01
Definition: TrackUnit.h:147
TRailGraphics::bmGreenRect
Graphics::TBitmap * bmGreenRect
Definition: GraphicUnit.h:520
TInterface::TTClockExitButtonClick
void __fastcall TTClockExitButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11678
TTrackElement::SpeedLimit01
int SpeedLimit01
Definition: TrackUnit.h:147
TTrack::IsReadyForOperation
bool IsReadyForOperation(bool GiveMessage)
Indicates whether or not the railway is ready for saving as a '.rly' file and for operation.
Definition: TrackUnit.h:726
TTrack::Raising
@ Raising
Definition: TrackUnit.h:523
TTrainController::FinishedOperation
void FinishedOperation(int Caller)
called when exiting operation mode to delete all trains and timetable data etc
Definition: TrainUnit.cpp:8254
TTextHandler::FindText
bool FindText(int Caller, AnsiString Name, int &HPos, int &VPos)
look in TextVector for text item 'Name', and if found return true and return its position in &HPos an...
Definition: TextUnit.cpp:557
TTrack::UserGraphicMove
void UserGraphicMove(int Caller, int HPosInput, int VPosInput, int &UserGraphicItem, int &UserGraphicMoveHPos, int &UserGraphicMoveVPos, bool &UserGraphicFoundFlag)
handles moving of user graphics
Definition: TrackUnit.cpp:9425
TDisplay::DisplayOffsetV
static int DisplayOffsetV
the vertical offset of the displayed screen
Definition: DisplayUnit.h:78
TTrain::MidElement
int MidElement
Definition: TrainUnit.h:327
TOneRoute::SetRouteFlashValues
void SetRouteFlashValues(int Caller, bool AutoSigsFlag, bool ConsecSignalsRoute)
After a route has been selected successfully this function sets all RouteFlash (see above) values app...
Definition: TrackUnit.cpp:16064
TInterface::SpeedButton5
TSpeedButton * SpeedButton5
Definition: InterfaceUnit.h:509
TInterface::LocationNameKeyUp
void __fastcall LocationNameKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:1152
TInterface::LoadUserGraphicDialog
TOpenDialog * LoadUserGraphicDialog
Definition: InterfaceUnit.h:491
TAllRoutes::CallonVector
std::vector< TCallonEntry > CallonVector
the store of all call-on entries
Definition: TrackUnit.h:1554
TInterface::OutputLog8MouseDown
void __fastcall OutputLog8MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11148
TInterface::SetPausedOrZoomedInfoCaption
void SetPausedOrZoomedInfoCaption(int Caller)
Sets the information panel message for zoom-out or paused modes.
Definition: InterfaceUnit.cpp:17770
TTrain::LeadElement
int LeadElement
Definition: TrainUnit.h:327
TInterface::CurDir
AnsiString CurDir
the full path to the folder where railway.exe resides
Definition: InterfaceUnit.h:904
TInterface::OneEntryTimetableMemoKeyUp
void __fastcall OneEntryTimetableMemoKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:4619
TInterface::RouteCancelButton
TBitBtn * RouteCancelButton
Definition: InterfaceUnit.h:198
TInterface::SpeedButton26
TSpeedButton * SpeedButton26
Definition: InterfaceUnit.h:530
TInterface::HomeButton
TBitBtn * HomeButton
Definition: InterfaceUnit.h:253
TRailGraphics
Handles graphic data & functions, single object defined.
Definition: GraphicUnit.h:308
TInterface::OperatorActionPanelDragStartY
int OperatorActionPanelDragStartY
as above for 'Y'
Definition: InterfaceUnit.h:1062
TTrain::RepeatNumber
int RepeatNumber
indicates which of the repeating services this train represents (0 = first service)
Definition: TrainUnit.h:321
TTrainDataEntry::ActionVector
TActionVector ActionVector
all the actions for the train
Definition: TrainUnit.h:195
TTrainController::BaseTime
TDateTime BaseTime
CurrentDateTime (i.e. real time) when operation restarts after a pause.
Definition: TrainUnit.h:638
TInterface::NewHomeButton
TBitBtn * NewHomeButton
Definition: InterfaceUnit.h:254
TInterface::ResetAll
void ResetAll(int Caller)
Called during ClearEverything and on startup to reset all major railway data values.
Definition: InterfaceUnit.cpp:15707
TInterface::SpeedButton75
TSpeedButton * SpeedButton75
Definition: InterfaceUnit.h:579
TTrainController::LoadSessionLockedRoutes
void LoadSessionLockedRoutes(int Caller, std::ifstream &SessionFile)
load locked routes from a session file
Definition: TrainUnit.cpp:14128
TInterface::DistancesMarked
bool DistancesMarked
true when setting lengths, used to ensure the screen distance markers are redisplayed when the screen...
Definition: InterfaceUnit.h:937
TTrainController::EarlyPasses
int EarlyPasses
Definition: TrainUnit.h:766
TTrain::HeadCode
AnsiString HeadCode
needs own HeadCode because repeat entries will differ from TrainDataEntry.HeadCode
Definition: TrainUnit.h:290
TInterface::TrackBuildPanel
TPanel * TrackBuildPanel
'Build/modify railway' panel
Definition: InterfaceUnit.h:357
TTrain::EntryTime
TDateTime EntryTime
Definition: TrainUnit.h:414
TInterface::CutMoving
@ CutMoving
Definition: InterfaceUnit.h:882
TInterface::SpeedButton134
TSpeedButton * SpeedButton134
Definition: InterfaceUnit.h:638
TInterface::SelectLengthsMenuItem
TMenuItem * SelectLengthsMenuItem
Definition: InterfaceUnit.h:439
TOnePrefDir::PrefDirSize
unsigned int PrefDirSize() const
Return the vector size.
Definition: TrackUnit.h:1275
TInterface::SpeedButton72
TSpeedButton * SpeedButton72
Definition: InterfaceUnit.h:576
TInterface::ValidateTimetableButton
TButton * ValidateTimetableButton
Definition: InterfaceUnit.h:144
TTrack::PlotSignal
void PlotSignal(int Caller, TTrackElement TrackElement, TDisplay *Disp)
Plot signals on screen according to their aspect (Attribute value)
Definition: TrackUnit.cpp:5426
TUserGraphicItem
Definition: DisplayUnit.h:31
TOneRoute::RouteFlash
TRouteFlash RouteFlash
the class member that allows the route to flash during setting up (see TRouteFlash above)
Definition: TrackUnit.h:1415
InterfaceUnit.h
TInterface::CopyMenuItemClick
void __fastcall CopyMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8946
TInterface::PerformanceLogButton
TBitBtn * PerformanceLogButton
Definition: InterfaceUnit.h:200
TInterface::FORMATTEDTT_DIR_NAME
static const UnicodeString FORMATTEDTT_DIR_NAME
Definition: InterfaceUnit.h:867
TInterface::HighLightOneGap
bool HighLightOneGap(int Caller, int &HLoc, int &VLoc)
Called during gap setting to mark a gap with a red ellipse and ask user to select the corresponding g...
Definition: InterfaceUnit.cpp:12717
TTrain::OneLengthAccelDecel
bool OneLengthAccelDecel
set when a train can only move forwards one element before stopping but needs to accelerate for the f...
Definition: TrainUnit.h:357
TTrain::FloatingLabelNextString
AnsiString FloatingLabelNextString(int Caller, TActionVectorEntry *Ptr)
Used in the floating window to display the 'Next' action.
Definition: TrainUnit.cpp:6416
TTrack::TActiveLevelCrossing::BarrierState
TBarrierState BarrierState
state of barriers
Definition: TrackUnit.h:534
TTrain::FailedTrainNoFinishJoinMessage
bool FailedTrainNoFinishJoinMessage
Definition: TrainUnit.h:302
TInterface::SpeedButton55
TSpeedButton * SpeedButton55
Definition: InterfaceUnit.h:559
TInterface::OperatorActionPanel
TPanel * OperatorActionPanel
new v2.2.0 panel housing the OAListBox with list of trains and times to act
Definition: InterfaceUnit.h:385
TInterface::NextTTEntryButton
TButton * NextTTEntryButton
Definition: InterfaceUnit.h:129
TTextHandler::SelectTextVectorSize
unsigned int SelectTextVectorSize(int Caller)
return the number of items in SelectTextVector
Definition: TextUnit.cpp:516
TInterface::TrackTrainFloat
void TrackTrainFloat(int Caller)
Controls the floating window function, called during the ClockTimer2 function.
Definition: InterfaceUnit.cpp:14369
TDisplay::GetImage
TImage * GetImage()
Return a pointer to the screen image.
Definition: DisplayUnit.h:138
clB0G0R5
#define clB0G0R5
Definition: GraphicUnit.h:41
TInterface::AddLocationNameText
void AddLocationNameText(int Caller, AnsiString Name, int HPos, int VPos, bool UseEnteredPosition)
Add 'Name' to TextVector and display on screen at a position determined by the shape and size of the ...
Definition: InterfaceUnit.cpp:18439
TTrack::InactiveTrackElementAt
TTrackElement & InactiveTrackElementAt(int Caller, int At)
A range-checked version of InactiveTrackElement.at(At)
Definition: TrackUnit.cpp:9531
TTextHandler::CheckTextElementsInFile
bool CheckTextElementsInFile(int Caller, std::ifstream &VecFile)
check the validity of text items in VecFile prior to loading, return true for success
Definition: TextUnit.cpp:349
TInterface::ConverttoRightHandSignalsMenuItemClick
void __fastcall ConverttoRightHandSignalsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12125
TPrefDirElement::GetTrackVectorPosition
unsigned int GetTrackVectorPosition() const
Returns TrackVectorPosition.
Definition: TrackUnit.h:295
TTrack::GetVLocMax
int GetVLocMax()
Definition: TrackUnit.h:780
TTrainController::LoadSessionContinuationAutoSigEntries
void LoadSessionContinuationAutoSigEntries(int Caller, std::ifstream &SessionFile)
load ContinuationAutoSigEntries from a session file
Definition: TrainUnit.cpp:14211
TInterface::HighlightOneEntryInAllEntriesTTListBox
void HighlightOneEntryInAllEntriesTTListBox(int Caller, int Position)
Called during timetable editing to highlight in red a single entry in the list of all entries in the ...
Definition: InterfaceUnit.cpp:5324
TInterface::DistanceStart
@ DistanceStart
Definition: InterfaceUnit.h:881
TInterface::ErrorMessage
TMemo * ErrorMessage
the text of the normal error message screen
Definition: InterfaceUnit.h:393
TInterface::ExitPrefDirButton
TBitBtn * ExitPrefDirButton
Definition: InterfaceUnit.h:121
TTrack::LNPendingList
TLNPendingList LNPendingList
list of location name elements awaiting processing (see type for more information above)
Definition: TrackUnit.h:701
TTrackElement
Basic track elements as implemented in the overall railway layout.
Definition: TrackUnit.h:123
TInterface::TrackLengthPanel
TPanel * TrackLengthPanel
the panel that contains the distance/speed setting buttons and edit boxes
Definition: InterfaceUnit.h:378
TUtilities::Format96HHMMSS
AnsiString Format96HHMMSS(TDateTime DateTime)
formats a TDateTime into an AnsiString of the form hh:mm:ss where hh runs from 00 to 95 & resets when...
Definition: Utilities.cpp:520
TTrack::RebuildUserGraphics
void RebuildUserGraphics(int Caller, TDisplay *Disp)
rebuild user graphics
Definition: TrackUnit.cpp:3423
TRailGraphics::bmSolidBgnd
Graphics::TBitmap * bmSolidBgnd
Definition: GraphicUnit.h:988
TRailGraphics::smSolidBgnd
Graphics::TBitmap * smSolidBgnd
Definition: GraphicUnit.h:989
TTrack::GroundSignalBuild
@ GroundSignalBuild
Definition: TrackUnit.h:757
TTrainController::OtherMissedEvents
int OtherMissedEvents
Definition: TrainUnit.h:775
TTextHandler::WriteTextToImage
void WriteTextToImage(int Caller, Graphics::TBitmap *Bitmap)
write all items in TextVector to the railway image in 'Bitmap'
Definition: TextUnit.cpp:425
TInterface::MoveTextOrGraphicButton
TBitBtn * MoveTextOrGraphicButton
Definition: InterfaceUnit.h:67
TTrainDataEntry::Description
AnsiString Description
headcode is the first train's headcode, rest are calculated from repeat information; ServiceReference...
Definition: TrainUnit.h:179
TInterface::RouteContinuing
@ RouteContinuing
Definition: InterfaceUnit.h:886
TTrain::ExitSpeedHalf
double ExitSpeedHalf
speed when half way into the next element
Definition: TrainUnit.h:379
SignalPost
@ SignalPost
Definition: TrackUnit.h:63
TTrack::SetAllDefaultLengthsAndSpeedLimits
void SetAllDefaultLengthsAndSpeedLimits(int Caller)
Work through all elements in TrackVector setting all lengths & speed limits to default values - inclu...
Definition: TrackUnit.cpp:8663
TTrain::LastActionTime
TDateTime LastActionTime
time of the last timetabled action, used to ensure at least a 30 second delay before the next action
Definition: TrainUnit.h:418
TAllRoutes::WriteAllRoutesToImage
void WriteAllRoutesToImage(int Caller, Graphics::TBitmap *Bitmap)
Calls RouteImageMarker for each route in turn to display the route colours and direction arrows on th...
Definition: TrackUnit.cpp:16218
IDInt::GetInt
int GetInt() const
get the internal integer
Definition: TrackUnit.h:421
TInterface::InfoPanel
TPanel * InfoPanel
the general information panel (with blue 'i' symbol)
Definition: InterfaceUnit.h:372
TInterface::TextOrUserGraphicGridButtonClick
void __fastcall TextOrUserGraphicGridButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1760
TInterface::FormKeyDown
void __fastcall FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:10583
TTrack::TActiveLevelCrossing::ConsecSignals
int ConsecSignals
route type - 0 = nonsignals, 1 = preferred direction (can't have autosigs), 2 no route,...
Definition: TrackUnit.h:530
TInterface::MoveTTEntryDownButton
TButton * MoveTTEntryDownButton
Definition: InterfaceUnit.h:135
TInterface::CheckTimetableFromSessionFile
bool CheckTimetableFromSessionFile(int Caller, std::ifstream &SessionFile)
Check the timetable file embedded within a session file & return false for error, called during Sessi...
Definition: InterfaceUnit.cpp:16883
TRailGraphics::SpeedBut71GrndBlackGlyph
Graphics::TBitmap * SpeedBut71GrndBlackGlyph
Definition: GraphicUnit.h:1055
TInterface::DeleteTTEntryButtonClick
void __fastcall DeleteTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3795
TTrack::GetScreenPositionsFromTruePos
void GetScreenPositionsFromTruePos(int Caller, int &ScreenPosH, int &ScreenPosV, int HPosTrue, int VPosTrue)
With large railways only part of the railway is displayed on screen, and this function converts true ...
Definition: TrackUnit.cpp:6888
TTrack::PlotPlainLoweredLinkedLevelCrossingBarriersAndSetMarkers
void PlotPlainLoweredLinkedLevelCrossingBarriersAndSetMarkers(int Caller, int BaseElementSpeedTag, int HLoc, int VLoc, TDisplay *Disp, bool Manual)
Plot LC elements without any base elements, and set LCPlotted true - used in ClearandRebuildRailway (...
Definition: TrackUnit.cpp:6170
TInterface::WarningFlashCount
int WarningFlashCount
increments each clock cycle to a max. of 4 then resets to 0, used to toggle bool WarningFlash - see a...
Definition: InterfaceUnit.h:1104
TInterface::StartWholeRailwayMoveHPos
int StartWholeRailwayMoveHPos
mouse X position when start to move the whole railway
Definition: InterfaceUnit.h:1082
TInterface::SpeedButton93
TSpeedButton * SpeedButton93
Definition: InterfaceUnit.h:597
TInterface::SpeedButton119
TSpeedButton * SpeedButton119
Definition: InterfaceUnit.h:623
TInterface::SelectedGraphicFileName
AnsiString SelectedGraphicFileName
filename for selected graphic set during LoadGraphic
Definition: InterfaceUnit.h:922
TTrack::EraseLocationAndActiveTrackElementNames
void EraseLocationAndActiveTrackElementNames(int Caller, AnsiString LocationName)
Examines LocationNameMultiMap and if the LocationName is found all elements at that H & V (in both ac...
Definition: TrackUnit.cpp:8003
TInterface::TrackBuildPanelLabel
TLabel * TrackBuildPanelLabel
label to the left of TrackBuildPanel
Definition: InterfaceUnit.h:315
clNormalBackground
#define clNormalBackground
Definition: GraphicUnit.h:297
TInterface::TTClockAdjButtonClick
void __fastcall TTClockAdjButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11647
TInterface::RAILWAY_DIR_NAME
static const UnicodeString RAILWAY_DIR_NAME
Definition: InterfaceUnit.h:862
TTrainController::SecondPassActions
bool SecondPassActions(int Caller, bool GiveMessages)
Carry out further detailed timetable consistency checks, return true for success.
Definition: TrainUnit.cpp:10828
TAllRoutes::MarkAllRoutes
void MarkAllRoutes(int Caller, TDisplay *Disp)
Calls PrefDirMarker for all routes, with RouteCall set to identify a route call, and BuildingPrefDir ...
Definition: TrackUnit.cpp:16203
TInterface::SPADImage
TImage * SPADImage
Definition: InterfaceUnit.h:266
TInterface::AddTrackButton
TBitBtn * AddTrackButton
Definition: InterfaceUnit.h:63
TInterface::MainMenu1
TMainMenu * MainMenu1
the program menu
Definition: InterfaceUnit.h:390
TInterface::OutputLog7MouseDown
void __fastcall OutputLog7MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11138
Concourse
@ Concourse
Definition: TrackUnit.h:64
TTextHandler::TTextVectorIterator
std::vector< TTextItem >::iterator TTextVectorIterator
Definition: TextUnit.h:66
TTrainController::SPADRisks
int SPADRisks
Definition: TrainUnit.h:777
TInterface::LocationNamesNotSetImage
TImage * LocationNamesNotSetImage
Definition: InterfaceUnit.h:279
TInterface::FloatingPanel
TPanel * FloatingPanel
new for v2.2.0 where label sits in it and it autosizes to the label. Labels are not TWinControls so t...
Definition: InterfaceUnit.h:382
TRailGraphics::SpeedBut68NormBlackGlyph
Graphics::TBitmap * SpeedBut68NormBlackGlyph
Definition: GraphicUnit.h:1044
TTrack::SelectVector
TTrackVector SelectVector
vectors of TrackElements
Definition: TrackUnit.h:710
TInterface::SaveMenuItemClick
void __fastcall SaveMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2442
TInterface::ScreenGridButtonClick
void __fastcall ScreenGridButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1864
TTrain::EntrySpeed
double EntrySpeed
speed at which the train enters the next element
Definition: TrainUnit.h:377
TInterface::UserGraphicMoveHPos
int UserGraphicMoveHPos
Definition: InterfaceUnit.h:1102
TInterface::PassRedSignalMenuItemClick
void __fastcall PassRedSignalMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10214
TInterface::ReselectMenuItem
TMenuItem * ReselectMenuItem
Definition: InterfaceUnit.h:431
TOnePrefDir::WritePrefDirToImage
void WritePrefDirToImage(int Caller, Graphics::TBitmap *Bitmap)
Used when creating a bitmap image to display preferred directions (as on screen during 'Set preferred...
Definition: TrackUnit.cpp:12386
TInterface::ClearEverything
bool ClearEverything(int Caller)
First check whether a railway file has changed and if so ask user if really wants to close it without...
Definition: InterfaceUnit.cpp:12745
TInterface::PrefDirContinuing
@ PrefDirContinuing
Definition: InterfaceUnit.h:877
TTrain::TrainGone
bool TrainGone
set when train has left the railway, so it can be removed from the display at the next clock tick
Definition: TrainUnit.h:428
TRailGraphics::SpeedBut70NormBlackGlyph
Graphics::TBitmap * SpeedBut70NormBlackGlyph
Definition: GraphicUnit.h:1046
TTrainController::OnTimePasses
int OnTimePasses
Definition: TrainUnit.h:774
TInterface::SaveAsMenuItem
TMenuItem * SaveAsMenuItem
Definition: InterfaceUnit.h:411
TInterface::MoveTextOrGraphicButtonClick
void __fastcall MoveTextOrGraphicButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1074
TTrainController::SigSHigh
bool SigSHigh
Definition: TrainUnit.h:743
TTrack::NoGaps
bool NoGaps(int Caller)
True if there are no gaps.
Definition: TrackUnit.cpp:4089
TInterface::ZoomButton
TBitBtn * ZoomButton
Definition: InterfaceUnit.h:255
TGraphicElement::PlotOriginal
void PlotOriginal(int Caller, TDisplay *Disp)
Plot the original graphic on screen.
Definition: TrackUnit.cpp:1597
TextHandler
TTextHandler * TextHandler
Definition: TextUnit.cpp:94
TInterface::CopyTTEntryButton
TButton * CopyTTEntryButton
Definition: InterfaceUnit.h:130
TInterface::ErrorMessageStoreImage
TMemo * ErrorMessageStoreImage
the text of the error message for failure to draw trains in SaveOperatingImage
Definition: InterfaceUnit.h:395
TInterface::SpeedButton76
TSpeedButton * SpeedButton76
Definition: InterfaceUnit.h:580
TTrain::StoppedAfterSPAD
bool StoppedAfterSPAD
Definition: TrainUnit.h:432
TInterface::SpeedButton145
TSpeedButton * SpeedButton145
Definition: InterfaceUnit.h:649
TInterface::NoPrefDirMode
@ NoPrefDirMode
Definition: InterfaceUnit.h:877
TInterface::SpeedButton88
TSpeedButton * SpeedButton88
Definition: InterfaceUnit.h:592
TTrainController::OnTimeArrivals
int OnTimeArrivals
Definition: TrainUnit.h:772
TInterface::MoveTTEntryDownButtonClick
void __fastcall MoveTTEntryDownButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4305
TInterface::PerformanceLogBox
TMemo * PerformanceLogBox
the performance log displayed during operation
Definition: InterfaceUnit.h:399
TRailGraphics::SpeedBut72GrndBlackGlyph
Graphics::TBitmap * SpeedBut72GrndBlackGlyph
Definition: GraphicUnit.h:1056
TInterface::SpeedButton28
TSpeedButton * SpeedButton28
Definition: InterfaceUnit.h:532
TAllRoutes::LevelCrossingBarrierUpDelay
const float LevelCrossingBarrierUpDelay
the full value in seconds for which the level crossing flashes prior to closing to trains
Definition: TrackUnit.h:1574
TInterface::SpeedTopLabel
TLabel * SpeedTopLabel
Definition: InterfaceUnit.h:180
TInterface::OperateButton
TBitBtn * OperateButton
Definition: InterfaceUnit.h:194
clFrontCodeSignaller
#define clFrontCodeSignaller
Definition: GraphicUnit.h:295
TInterface::SignallerJoinedByMenuItemClick
void __fastcall SignallerJoinedByMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10035
TTrack::MirrorArray
int MirrorArray[FirstUnusedSpeedTagNumber]
holds TrackElement SpeedTag values for 'mirroring' via menu items 'Edit' & 'Mirror'
Definition: TrackUnit.h:675
TUserGraphicItem::Width
int Width
Definition: DisplayUnit.h:35
Utilities
TUtilities * Utilities
Definition: Utilities.cpp:47
TActionVectorEntry::ArrivalTime
TDateTime ArrivalTime
Definition: TrainUnit.h:106
TTrain::StoppedAtBuffers
bool StoppedAtBuffers
Definition: TrainUnit.h:432
TInterface::SkipFormResizeEvent
bool SkipFormResizeEvent
added at v2.1.0 to avoid calling the event during startup and shutdown
Definition: InterfaceUnit.h:981
TTrain::Mass
int Mass
in kg
Definition: TrainUnit.h:408
TInterface::TrackInfoOnOffMenuItem
TMenuItem * TrackInfoOnOffMenuItem
Definition: InterfaceUnit.h:445
TDisplay::ShowWarningLog
void ShowWarningLog(int Caller)
Show the warnings after timetable clock adjusted.
Definition: DisplayUnit.cpp:493
TInterface::SpeedButton121
TSpeedButton * SpeedButton121
Definition: InterfaceUnit.h:625
TTrainController::ProcessOneTimetableLine
bool ProcessOneTimetableLine(int Caller, int Count, AnsiString OneLine, bool &EndOfFile, bool FinalCall, bool GiveMessages, bool CheckLocationsExistInRailway)
Carry out preliminary (mainly syntax) validity checks on a single timetable service entry and (if Fin...
Definition: TrainUnit.cpp:9138
TInterface::SaveAsMenuItemClick
void __fastcall SaveAsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2493
TTextItem
A single piece of text that can be displayed on the railway.
Definition: TextUnit.h:36
TInterface::SpeedButton136
TSpeedButton * SpeedButton136
Definition: InterfaceUnit.h:640
TInterface::PointFlash
TGraphicElement * PointFlash
Definition: InterfaceUnit.h:1118
TInterface::TrackLinkedImage
TImage * TrackLinkedImage
Definition: InterfaceUnit.h:274
TTrain::LeadExitPos
int LeadExitPos
Definition: TrainUnit.h:327
TInterface::SelectPickedUp
bool SelectPickedUp
true when a valid selected screen area has been clicked after a 'Copy' or 'Cut' selected in the 'Edit...
Definition: InterfaceUnit.h:975
TDisplay::ResetZoomOutOffsets
void ResetZoomOutOffsets()
Reset the zoomed-out screen display to the 'Home' position.
Definition: DisplayUnit.h:208
TTrackElement::ThreeAspect
@ ThreeAspect
Definition: TrackUnit.h:156
TInterface::DevelopmentPanel
TPanel * DevelopmentPanel
used for diagnostic purposes, made visible by ctrl+ alt+ 3
Definition: InterfaceUnit.h:380
TTrack::NoActiveOrInactiveTrack
bool NoActiveOrInactiveTrack(int Caller)
True if there is no active or inactive track in the railway.
Definition: TrackUnit.cpp:1616
TInterface::PerformancePanel
TPanel * PerformancePanel
displays the operating performance log
Definition: InterfaceUnit.h:374
TTrainController::DerailWarning
bool DerailWarning
Definition: TrainUnit.h:729
TInterface::CopyMoving
@ CopyMoving
Definition: InterfaceUnit.h:882
TInterface::TimetableEditPanel
TPanel * TimetableEditPanel
the large panel that contains all the main timetable components
Definition: InterfaceUnit.h:366
TInterface::RouteMode
enum TInterface::@0 RouteMode
route building modes
TDisplay::DisplayZoomOutOffsetVHome
static int DisplayZoomOutOffsetVHome
the vertical offset of the zoomed-out 'Home' display
Definition: DisplayUnit.h:90
TInterface::TrainStatusInfoOnOffMenuItem
TMenuItem * TrainStatusInfoOnOffMenuItem
Definition: InterfaceUnit.h:447
TInterface::SetLengthsButtonClick
void __fastcall SetLengthsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1339
TInterface::SaveTTEntryButton
TButton * SaveTTEntryButton
Definition: InterfaceUnit.h:136
TInterface::SpeedButton37
TSpeedButton * SpeedButton37
Definition: InterfaceUnit.h:541
TInterface::BaseMode
@ BaseMode
Definition: InterfaceUnit.h:851
TInterface::SpeedEditBoxKeyUp
void __fastcall SpeedEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:11342
TTrack::DiagonalFouledByTrain
bool DiagonalFouledByTrain(int Caller, int HLoc, int VLoc, int DiagonalLinkNumber, int &TrainID)
As DiagonalFouledByRouteOrTrain (in TAllRoutes) but only checks for a train (may or may not be a rout...
Definition: TrackUnit.cpp:10211
TInterface::MirrorMenuItem
TMenuItem * MirrorMenuItem
Definition: InterfaceUnit.h:435
TInterface::EveryPrefDir
TOnePrefDir * EveryPrefDir
all the Pref Dir elements in the railway
Definition: InterfaceUnit.h:1129
TTrainController::TotLateDepMins
float TotLateDepMins
Definition: TrainUnit.h:759
TDisplay::ZoomOutFlag
bool ZoomOutFlag
true when zoomed-out
Definition: DisplayUnit.h:69
TInterface::OutputLog8
TLabel * OutputLog8
Definition: InterfaceUnit.h:299
TInterface::SpeedButton1
TSpeedButton * SpeedButton1
See Speedbutton1 detail for track element allocations.
Definition: InterfaceUnit.h:505
TTrainController::TrainVector
TTrainVector TrainVector
vector containing all trains currently in the railway
Definition: TrainUnit.h:807
TInterface::SaveAsSubroutine
void SaveAsSubroutine(int Caller)
Used to save a railway when not already saved - e.g. when not already named or when the 'Save as' men...
Definition: InterfaceUnit.cpp:18233
TInterface::MainScreenMouseDown2
void MainScreenMouseDown2(int Caller, TMouseButton Button, TShiftState Shift, int X, int Y)
Called when mouse button clicked in zoom-in mode.
Definition: InterfaceUnit.cpp:5631
TOneRoute::ClearRoute
void ClearRoute()
Empty the route of any stored elements.
Definition: TrackUnit.h:1421
TInterface::RepairFailedTrainMenuItemClick
void __fastcall RepairFailedTrainMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10124
TInterface::AddLocationName
@ AddLocationName
Definition: InterfaceUnit.h:881
TTrack::LocationNameAllocated
bool LocationNameAllocated(int Caller, AnsiString LocationName)
True if a non-empty LocationName found in LocationNameMultiMap.
Definition: TrackUnit.cpp:7807
TTrack::IsTrackFinished
bool IsTrackFinished()
Indicates whether or not the track has been successfully linked together.
Definition: TrackUnit.h:732
TAllRoutes::AllRoutesClear
void AllRoutesClear()
Erases all routes from AllRoutesVector and from Route2MultiMap.
Definition: TrackUnit.h:1602
TRailGraphics::SpeedBut74GrndBlackGlyph
Graphics::TBitmap * SpeedBut74GrndBlackGlyph
Definition: GraphicUnit.h:1058
TAllRoutes::PointsDelay
const float PointsDelay
the value in seconds for which points flash prior to being changed. Used for the points flash period ...
Definition: TrackUnit.h:1578
TInterface::SaveSession
void SaveSession(int Caller)
Save a session file - see LoadSession for details of additions to the session file.
Definition: InterfaceUnit.cpp:15915
TUtilities::CallLogPop
void CallLogPop(int Caller)
pops the last entry off the call stack, throws an error if called when empty
Definition: Utilities.cpp:50
TAllRoutes::SignalsDelay
const float SignalsDelay
the value in seconds for which signals flash prior to being changed. Used for the route flash period ...
Definition: TrackUnit.h:1580
TDisplay::GetFont
TFont * GetFont()
Return the current screen font.
Definition: DisplayUnit.h:132
TInterface::SpeedButton10
TSpeedButton * SpeedButton10
Definition: InterfaceUnit.h:514
TTrain::MaximumSpeedLimit
static const int MaximumSpeedLimit
km/h
Definition: TrainUnit.h:284
TInterface::SpeedButton103
TSpeedButton * SpeedButton103
Definition: InterfaceUnit.h:607
TTrack::ThreeAspectBuild
@ ThreeAspectBuild
Definition: TrackUnit.h:757
TTrainController::TotEarlyArrMins
float TotEarlyArrMins
values for performance file summary
Definition: TrainUnit.h:755
TInterface::PerformancePanelStartDrag
void __fastcall PerformancePanelStartDrag(TObject *Sender, TDragObject *&DragObject)
Definition: InterfaceUnit.cpp:5559
TInterface::TempCursorSet
bool TempCursorSet
indicates that a screen cursor has been stored in TempCursor for redisplay after a temporary cursor (...
Definition: InterfaceUnit.h:983
TOnePrefDir::GetPrefDirTruncateElement
bool GetPrefDirTruncateElement(int Caller, int HLoc, int VLoc)
Called during PrefDir build or distance setting. It truncates at & including the first element in the...
Definition: TrackUnit.cpp:11189
TInterface::SpeedButton85
TSpeedButton * SpeedButton85
Definition: InterfaceUnit.h:589
TInterface::PasteMenuItemClick
void __fastcall PasteMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9532
TInterface::MainScreenMouseUp
void __fastcall MainScreenMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:7359
TDisplay::PlotOutput
void PlotOutput(int Caller, int HPos, int VPos, Graphics::TBitmap *PlotItem)
Plot the graphic at screen position HPos & VPos.
Definition: DisplayUnit.cpp:85
TInterface::SaveTempTimetableFile
void SaveTempTimetableFile(int Caller, AnsiString InFileName)
Save a timetable as a temporary file either on loading directly or on loading a session file....
Definition: InterfaceUnit.cpp:17994
TAllRoutes::AllRoutesVector
TAllRoutesVector AllRoutesVector
the vector that stores all the routes on the railway
Definition: TrackUnit.h:1584
TUtilities::SaveFileBool
void SaveFileBool(std::ofstream &OutFile, bool SaveBool)
stores '1' if the bool is true or '0' if false to the file, then a CR
Definition: Utilities.cpp:108
TInterface::RotateMenuItemClick
void __fastcall RotateMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9081
TTrainDataEntry::SignallerSpeed
int SignallerSpeed
in km/h for use when under signaller control
Definition: TrainUnit.h:191
TInterface::OverallDistance
int OverallDistance
Definition: InterfaceUnit.h:1064
TInterface::SpeedButton105
TSpeedButton * SpeedButton105
Definition: InterfaceUnit.h:609
TInterface::SpeedButton83
TSpeedButton * SpeedButton83
Definition: InterfaceUnit.h:587
TTrain::AbleToMove
bool AbleToMove(int Caller)
Indicates that a train is not prevented from moving - used to allow appropriate popup menu options wh...
Definition: TrainUnit.cpp:6281
TTrainController::MTBFHours
double MTBFHours
Mean time between failures in timetable clock hours.
Definition: TrainUnit.h:746
TOnePrefDir::SaveSearchVector
void SaveSearchVector(int Caller, std::ofstream &VecFile)
Save the search vector to a file.
Definition: TrackUnit.cpp:11669
TInterface::RestoreAllDefaultLengthsButtonClick
void __fastcall RestoreAllDefaultLengthsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1670
TInterface::LengthWarningSentFlag
bool LengthWarningSentFlag
indicates that the length selection applying to all elements in the selection warning has been given,...
Definition: InterfaceUnit.h:947
TInterface::SpeedButton131
TSpeedButton * SpeedButton131
Definition: InterfaceUnit.h:635
TOneRoute::GetNextPreferredRouteElement
bool GetNextPreferredRouteElement(int Caller, int HLoc, int VLoc, TOnePrefDir *EveryPrefDir, bool ConsecSignalsRoute, bool AutoSigsFlag, IDInt &ReqPosRouteID, bool &PointsChanged)
Try to find a set of linked tracks that lie on preferred directions between the route start element a...
Definition: TrackUnit.cpp:13208
TInterface::FlipMenuItemClick
void __fastcall FlipMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8965
TInterface::TrainTTInfoOnOffMenuItem
TMenuItem * TrainTTInfoOnOffMenuItem
Definition: InterfaceUnit.h:448
TInterface::AllSetUpFlag
bool AllSetUpFlag
false during initial start up, true when all set up to allow MasterClock to start
Definition: InterfaceUnit.h:925
TTrack::SaveChangingLCVector
void SaveChangingLCVector(int Caller, std::ofstream &OutFile)
Save all changing vector values (used for error file)
Definition: TrackUnit.cpp:3241
TInterface::LocationNameButton
TBitBtn * LocationNameButton
Definition: InterfaceUnit.h:68
TInterface::SpeedButton101
TSpeedButton * SpeedButton101
Definition: InterfaceUnit.h:605
TTrain::TrainMode
TTrainMode TrainMode
mode of operation - either Timetable (running under timetable control) or Signaller (running under si...
Definition: TrainUnit.h:420
TInterface::LoadRailway
void LoadRailway(int Caller, AnsiString LoadFileName)
Load a railway file. The Active elements marker now has a '1' at the end if there are user graphics t...
Definition: InterfaceUnit.cpp:2312
TTrack::SaveUserGraphics
void SaveUserGraphics(int Caller, std::ofstream &VecFile)
save graphics
Definition: TrackUnit.cpp:10258
TInterface::TextOrUserGraphicGridButton
TBitBtn * TextOrUserGraphicGridButton
Definition: InterfaceUnit.h:70
TInterface::PointFlashVectorPosition
int PointFlashVectorPosition
Definition: InterfaceUnit.h:1071
TInterface::AddSubMinsBoxKeyUp
void __fastcall AddSubMinsBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:4644
TInterface::ExitOperationButtonClick
void __fastcall ExitOperationButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2214
TGraphicElement::LoadOriginalScreenGraphic
void LoadOriginalScreenGraphic(int Caller)
Load original graphic from the screen for point flashing or route start markers.
Definition: TrackUnit.cpp:1499
TInterface::TTClockAdd1hButtonClick
void __fastcall TTClockAdd1hButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11890
TUtilities::Format96HHMM
AnsiString Format96HHMM(TDateTime DateTime)
formats a TDateTime into an AnsiString of the form hh:mm where hh runs from 00 to 95 & resets when it...
Definition: Utilities.cpp:535
TInterface::TTClockx2ButtonClick
void __fastcall TTClockx2ButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11720
TInterface::PerformancePanelDragStartX
int PerformancePanelDragStartX
mouse 'X' position when the performance panel begins to be dragged
Definition: InterfaceUnit.h:1067
TInterface::SpeedButton45
TSpeedButton * SpeedButton45
Definition: InterfaceUnit.h:549
TInterface::SpeedEditBox2KeyUp
void __fastcall SpeedEditBox2KeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:11496
TInterface::SavedFileName
AnsiString SavedFileName
the full path and filename of the loaded railway
Definition: InterfaceUnit.h:916
TInterface::FillSelectionMessageSentFlag
bool FillSelectionMessageSentFlag
indicates that the message about filling a selected area with a chosen track element has been given,...
Definition: InterfaceUnit.h:943
TInterface::PlanPrefDirsMenuItemClick
void __fastcall PlanPrefDirsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1891
TInterface::OperatingPanel
TPanel * OperatingPanel
'Operate railway' panel
Definition: InterfaceUnit.h:363
TTrack::SelectVectorSize
unsigned int SelectVectorSize()
Return the number of selected active and inactive track elements (via menu items 'Edit' and 'Select')
Definition: TrackUnit.h:818
TInterface::SpeedButton141
TSpeedButton * SpeedButton141
Definition: InterfaceUnit.h:645
TInterface::ShowOperatorActionPanel
bool ShowOperatorActionPanel
true when the 'trains needing action' button has been clicked during operation (new at v2....
Definition: InterfaceUnit.h:997
TTrack::GetGapVLoc
int GetGapVLoc()
Definition: TrackUnit.h:765
TInterface::SpeedButton124
TSpeedButton * SpeedButton124
Definition: InterfaceUnit.h:628
TUtilities::CheckFileString
bool CheckFileString(std::ifstream &InFile)
checks that the value is a string ('0' or CR accepted as delimiters), returns true for success
Definition: Utilities.cpp:356
TOnePrefDir::LoadPrefDir
void LoadPrefDir(int Caller, std::ifstream &VecFile)
Load a vector and map of preferred directions from the file.
Definition: TrackUnit.cpp:11489
TRailGraphics::bmGrid
Graphics::TBitmap * bmGrid
Definition: GraphicUnit.h:521
TInterface::RestoreFocusPanel
TPanel * RestoreFocusPanel
Panel used to restore focus to Interface to enable cursor keys to move screen.
Definition: InterfaceUnit.h:354
TInterface::BlackBgndMenuItem
TMenuItem * BlackBgndMenuItem
Definition: InterfaceUnit.h:426
SignallerControlStop
@ SignallerControlStop
Definition: TrainUnit.h:51
TTrack::TrackVector
TTrackVector TrackVector
Definition: TrackUnit.h:710
TTrack::TActiveLevelCrossing::BaseElementSpeedTag
int BaseElementSpeedTag
SpeedTag value for the base element of a level crossing.
Definition: TrackUnit.h:538
TInterface::FloatingLabel
TLabel * FloatingLabel
the floating window that displays track & train information
Definition: InterfaceUnit.h:335
TInterface::NewTTEntryButton
TButton * NewTTEntryButton
Definition: InterfaceUnit.h:138
TTrainController::ExcessLCDownMins
float ExcessLCDownMins
total excess time in minutes over the 3 minutes barriers down allowance for level crossings
Definition: TrainUnit.h:753
TInterface::SubMinsButtonClick
void __fastcall SubMinsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3547
TGraphicElement
Allows a single Width x Height graphic to change and change back independently of the remaining displ...
Definition: TrackUnit.h:346
TInterface::TimetableControlMenuItemClick
void __fastcall TimetableControlMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9824
TTrack::TActiveTrackElementNameIterator
TActiveTrackElementNameMap::iterator TActiveTrackElementNameIterator
Definition: TrackUnit.h:617
TInterface::DistanceBox
TEdit * DistanceBox
distance/speed setting edit box that accepts distances
Definition: InterfaceUnit.h:90
TInterface::SpeedButton142
TSpeedButton * SpeedButton142
Definition: InterfaceUnit.h:646
TInterface::PresetAutoSigRoutesButton
TBitBtn * PresetAutoSigRoutesButton
Definition: InterfaceUnit.h:199
TTrackElement::CallingOnSet
bool CallingOnSet
Used for for signals only when a train is being called on - used to plot the position lights.
Definition: TrackUnit.h:133
TUtilities::SaveFileInt
void SaveFileInt(std::ofstream &OutFile, int SaveInt)
stores the int value to the file, then a CR
Definition: Utilities.cpp:117
TInterface::TTLabel12
TLabel * TTLabel12
Definition: InterfaceUnit.h:349
TInterface::TTServiceSyntaxCheckButtonClick
void __fastcall TTServiceSyntaxCheckButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4156
TInterface::SpeedButton57
TSpeedButton * SpeedButton57
Definition: InterfaceUnit.h:561
TInterface::TTClockSpeed
float TTClockSpeed
rate at which the timetable clock runs 1 = normal
Definition: InterfaceUnit.h:1039
TrainController
TTrainController * TrainController
the object pointer, one object only - created in InterfaceUnit
Definition: TrainUnit.cpp:54
TDisplay::PlotAbsolute
void PlotAbsolute(int Caller, int HPos, int VPos, Graphics::TBitmap *PlotItem)
Definition: DisplayUnit.cpp:419
TTrack::TrackElementPresentAtHV
bool TrackElementPresentAtHV(int Caller, int HLoc, int VLoc)
New at v1.2.0; true if a track element present (not inactive elements - see InactiveTrackElementPrese...
Definition: TrackUnit.cpp:5154
TGraphicElement::LoadOriginalExistingGraphic
void LoadOriginalExistingGraphic(int Caller, int HOffset, int VOffset, int WidthIn, int HeightIn, Graphics::TBitmap *Graphic)
Load red or green gap flashing graphic from the stored bitmaps.
Definition: TrackUnit.cpp:1533
TInterface::TTClockx4ButtonClick
void __fastcall TTClockx4ButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11739
TOnePrefDir::CalcDistanceAndSpeed
void CalcDistanceAndSpeed(int Caller, int &OverallDistance, int &OverallSpeedLimit, bool &LeadingPointsAtLastElement)
Used when setting element lengths, returns in &OverallDistance the overall distance for the selected ...
Definition: TrackUnit.cpp:12323
TTextHandler::TextFound
bool TextFound(int Caller, int HPosInput, int VPosInput, AnsiString &Text)
look for a text item in the vicinity of HPosInput & VPosInput, return true if found & return the foun...
Definition: TextUnit.cpp:225
TInterface::LCManualLowerBarriersMessageSent
bool LCManualLowerBarriersMessageSent
indicates that the manual LC operation message has been given, so it won't be given again
Definition: InterfaceUnit.h:945
TInterface::SaveImageAndPrefDirsMenuItemClick
void __fastcall SaveImageAndPrefDirsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2699
TInterface::AddMinsButton
TButton * AddMinsButton
Definition: InterfaceUnit.h:141
SignallerStepForward
@ SignallerStepForward
Definition: TrainUnit.h:51
TTrack::GetHLocMin
int GetHLocMin()
Definition: TrackUnit.h:775
TTextHandler::TextPtrAt
TTextItem * TextPtrAt(int Caller, int At)
return the text item at position 'At' in TextVector (carries out range checking)
Definition: TextUnit.cpp:527
TInterface::SpeedButton60
TSpeedButton * SpeedButton60
Definition: InterfaceUnit.h:564
TInterface::TrackInfoOnOffMenuItemClick
void __fastcall TrackInfoOnOffMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:5431
TTrack::WriteTrackToImage
void WriteTrackToImage(int Caller, Graphics::TBitmap *Bitmap)
Called by TInterface::SaveImageNoGrid1Click, TInterface::SaveImageAndGrid1Click and TInterface::SaveI...
Definition: TrackUnit.cpp:3449
TTrainController::OpTimeToActUpdateCounter
unsigned int OpTimeToActUpdateCounter
new v2.2.0, incremented in Interface.cpp, controls updating for OpTimeToActPanel
Definition: TrainUnit.h:791
TTrain::BeingCalledOn
bool BeingCalledOn
in course of being called on to a station
Definition: TrainUnit.h:341
TUtilities::CheckFileInt
bool CheckFileInt(std::ifstream &InFile, int Lowest, int Highest)
checks that the value is an int lying between Lowest & Highest (inclusive), returns true for success
Definition: Utilities.cpp:217
TInterface::AZOrderButtonClick
void __fastcall AZOrderButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4966
TInterface::HiddenScreen
TImage * HiddenScreen
a hidden copy of the railway display screen used during ClearandRebuildRailway (see below) to avoid f...
Definition: InterfaceUnit.h:1124
TInterface::PerformancePanelLabelStartDrag
void __fastcall PerformancePanelLabelStartDrag(TObject *Sender, TDragObject *&DragObject)
Definition: InterfaceUnit.cpp:10491
TInterface::LoadPerformanceFile
void LoadPerformanceFile(int Caller, std::ifstream &InFile)
Load the performance file part of a sessionfile.
Definition: InterfaceUnit.cpp:17624
TInterface::CPCancelButtonClick
void __fastcall CPCancelButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12395
TInterface::OutputLog4MouseDown
void __fastcall OutputLog4MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11109
TInterface::AddGraphic
@ AddGraphic
Definition: InterfaceUnit.h:881
TInterface::SetLevel1Mode
void SetLevel1Mode(int Caller)
Sets the Level1 user mode, using the Level1Mode variable to determine the mode.
Definition: InterfaceUnit.cpp:12977
TInterface::NewHomeButtonClick
void __fastcall NewHomeButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8795
TInterface::OutputLog4
TLabel * OutputLog4
Definition: InterfaceUnit.h:295
TInterface::FontDialog
TFontDialog * FontDialog
font change dialog
Definition: InterfaceUnit.h:496
TInterface::TrackSelecting
@ TrackSelecting
Definition: InterfaceUnit.h:882
TTrainController::TotLateArrMins
float TotLateArrMins
Definition: TrainUnit.h:758
TInterface::Level2PrefDirMode
enum TInterface::TLevel2PrefDirMode Level2PrefDirMode
TInterface::OperatingPanelLabel
TLabel * OperatingPanelLabel
displays 'Operation' or 'Disabled' on the operating panel during operation for running or paused
Definition: InterfaceUnit.h:323
TInterface::DivergingPointVectorPosition
int DivergingPointVectorPosition
Definition: InterfaceUnit.h:1071
TInterface::OAListBoxMouseUp
void __fastcall OAListBoxMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:4739
TTrainController::PlotAllTrainsInZoomOutMode
void PlotAllTrainsInZoomOutMode(int Caller, bool Flash)
Plots all trains on screen in zoomed-out mode, state of 'Flash' determines whether the flashing train...
Definition: TrainUnit.cpp:14364
TInterface::SpeedButton108
TSpeedButton * SpeedButton108
Definition: InterfaceUnit.h:612
TOneRoute
A descendent of TOnePrefDir used for routes. Used during contruction of a route (ConstructRoute) and ...
Definition: TrackUnit.h:1371
TTrack::NamedLocationElementAt
bool NamedLocationElementAt(int Caller, int HLoc, int VLoc)
True if the active or inactive TrackElement at HLoc & VLoc has its FixedNamedLocationElement member t...
Definition: TrackUnit.cpp:7774
TInterface::SavePerformanceFile
void SavePerformanceFile(int Caller, std::ofstream &OutFile)
Save performance file part of a session file.
Definition: InterfaceUnit.cpp:17679
TTextItem::Font
TFont * Font
the text font
Definition: TextUnit.h:52
TAllRoutes::TLockedRouteVectorIterator
std::vector< TLockedRouteClass >::iterator TLockedRouteVectorIterator
Definition: TrackUnit.h:1525
TTrain::SignallerStopped
bool SignallerStopped
Definition: TrainUnit.h:432
TDisplay::SetFont
void SetFont(TFont *Font)
Set the screen font to 'Font'.
Definition: DisplayUnit.h:215
TAllRoutes::TRouteType
TRouteType
Definition: TrackUnit.h:1515
TTrain::TrainDataEntryPtr
TTrainDataEntry * TrainDataEntryPtr
points to the current position in the timetable's TrainDataVector
Definition: TrainUnit.h:333
TInterface::TTLabel13
TLabel * TTLabel13
Definition: InterfaceUnit.h:350
TTrainDataEntry::StartSpeed
int StartSpeed
in km/h
Definition: TrainUnit.h:193
TTrainDataEntry::NumberOfTrains
int NumberOfTrains
number of repeats + 1
Definition: TrainUnit.h:189
TTrainController::Derailments
int Derailments
Definition: TrainUnit.h:764
clStationStopBackground
#define clStationStopBackground
Definition: GraphicUnit.h:301
TInterface::AZOrderButton
TButton * AZOrderButton
Definition: InterfaceUnit.h:140
TInterface::SpeedButton86
TSpeedButton * SpeedButton86
Definition: InterfaceUnit.h:590
TInterface::SpeedButton122
TSpeedButton * SpeedButton122
Definition: InterfaceUnit.h:626
Crossover
@ Crossover
Definition: TrackUnit.h:63
TTrack::SetLinkedManualLCs
void SetLinkedManualLCs(int Caller, int HLoc, int VLoc)
Set all ConsecSignals values to 2 for all linked LCs to indicate manually lowered.
Definition: TrackUnit.cpp:5633
TInterface::SpeedButton104
TSpeedButton * SpeedButton104
Definition: InterfaceUnit.h:608
TInterface::SignallerJoinedByMenuItem
TMenuItem * SignallerJoinedByMenuItem
Definition: InterfaceUnit.h:477
TRailGraphics::SpeedBut69NormBlackGlyph
Graphics::TBitmap * SpeedBut69NormBlackGlyph
Definition: GraphicUnit.h:1045
TTrack::IsLCBarrierFlashingAtHV
bool IsLCBarrierFlashingAtHV(int Caller, int HLoc, int VLoc)
True if barrier is in process of opening or closing at H & V.
Definition: TrackUnit.cpp:6622
TDisplay::ResetZoomInOffsets
void ResetZoomInOffsets()
Reset the zoomed-in screen display to the 'Home' position.
Definition: DisplayUnit.h:201
TTrack::IsPlatformOrNamedNonStationLocationPresent
bool IsPlatformOrNamedNonStationLocationPresent(int Caller, int HLoc, int VLoc)
True if a non-station named location or platform at HLoc & VLoc.
Definition: TrackUnit.cpp:9017
TInterface::RotRightMenuItem
TMenuItem * RotRightMenuItem
Definition: InterfaceUnit.h:475
AtLocation
@ AtLocation
Definition: TrainUnit.h:67
TInterface::ExportTTButton
TButton * ExportTTButton
Definition: InterfaceUnit.h:148
DefaultTrackLength
#define DefaultTrackLength
Definition: TrackUnit.h:37
Signal
@ Signal
Definition: TrackUnit.h:73
TInterface::TimetableChangedFlag
bool TimetableChangedFlag
true when a timetable in the editor has changed (used to warn user if opts to exit without saving)
Definition: InterfaceUnit.h:991
TInterface::SaveTimetableToErrorFile
bool SaveTimetableToErrorFile(int Caller, std::ofstream &ErrorFile, AnsiString ErrorFileStr, AnsiString TimetableFileName)
Called when compiling the error log file, to save the loaded timetable if any and the timetable being...
Definition: InterfaceUnit.cpp:16687
TTrack::ContinuationNameMap
std::map< AnsiString, char > ContinuationNameMap
map of all continuation names, char is a dummy
Definition: TrackUnit.h:682
TAllRoutes::GetRouteTypeAndNumber
TRouteType GetRouteTypeAndNumber(int Caller, int TrackVectorPosition, int LinkPos, int &RouteNumber)
Examines Route2MultiMap and if the element at TrackVectorPosition with LinkPos (can be entry or exit)...
Definition: TrackUnit.cpp:16506
TTrackElement::TrainIDOnBridgeTrackPos01
int TrainIDOnBridgeTrackPos01
Definition: TrackUnit.h:151
TInterface::TrainHeadCodeMenuItem
TMenuItem * TrainHeadCodeMenuItem
Definition: InterfaceUnit.h:459
TTrainController::TrainDataVector
TTrainDataVector TrainDataVector
vector containing the internal timetable
Definition: TrainUnit.h:805
TOnePrefDir::CheckOnePrefDir
bool CheckOnePrefDir(int Caller, int NumberOfActiveElements, std::ifstream &VecFile)
Called before PrefDir loading as part of the FileIntegrityCheck function in case there is an error in...
Definition: TrackUnit.cpp:11539
TAllRoutes::NotAutoSigsRoute
@ NotAutoSigsRoute
Definition: TrackUnit.h:1516
TTrain::ExitTimeHalf
TDateTime ExitTimeHalf
Definition: TrainUnit.h:414
Exited
@ Exited
Definition: TrainUnit.h:80
TInterface::OutputLog2
TLabel * OutputLog2
Definition: InterfaceUnit.h:293
TInterface::TTClockAdjustWarningLabel
TLabel * TTClockAdjustWarningLabel
Definition: InterfaceUnit.h:230
TInterface::SpeedButton74
TSpeedButton * SpeedButton74
Definition: InterfaceUnit.h:578
TInterface::ScreenRightButtonClick
void __fastcall ScreenRightButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8448
TInterface::PositionalPanel
TPanel * PositionalPanel
Definition: InterfaceUnit.h:384
TInterface::StepForwardMenuItemClick
void __fastcall StepForwardMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10257
TInterface::ErrorLog
void ErrorLog(int Caller, AnsiString Message)
The error logging routine, called when an error is detected.
Definition: InterfaceUnit.cpp:15578
TInterface::SpeedButton50
TSpeedButton * SpeedButton50
Definition: InterfaceUnit.h:554
TTrack::TrackElementAt
TTrackElement & TrackElementAt(int Caller, int At)
A range-checked version of TrackElement.at(At)
Definition: TrackUnit.cpp:9518
TTrainController::LoadSessionTrains
void LoadSessionTrains(int Caller, std::ifstream &SessionFile)
load trains from a session file
Definition: TrainUnit.cpp:14061
TInterface::SpeedButton31
TSpeedButton * SpeedButton31
Definition: InterfaceUnit.h:535
TInterface::UserGraphicFoundFlag
bool UserGraphicFoundFlag
indicates that a user graphic item has been found when clicking on a build screen for moving
Definition: InterfaceUnit.h:989
TInterface::RouteCancelButtonClick
void __fastcall RouteCancelButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2165
TInterface::SpeedButton91
TSpeedButton * SpeedButton91
Definition: InterfaceUnit.h:595
TInterface::SelectedTrainID
int SelectedTrainID
used to store the train ID when right clicked for signaller control actions
Definition: InterfaceUnit.h:1080
TInterface::SpeedButton113
TSpeedButton * SpeedButton113
Definition: InterfaceUnit.h:617
TInterface::SpeedButton82
TSpeedButton * SpeedButton82
Definition: InterfaceUnit.h:586
TTextHandler::SelectTextPtrAt
TTextItem * SelectTextPtrAt(int Caller, int At)
return the text item at position 'At' in SelectTextVector (carries out range checking)
Definition: TextUnit.cpp:542
TInterface::SpeedButton132
TSpeedButton * SpeedButton132
Definition: InterfaceUnit.h:636
TTrack::ChangingLCVector
TActiveLCVector ChangingLCVector
vector of values for changing level crossings - i.e. barriers in course of being raised or lowered
Definition: TrackUnit.h:687
TInterface::FlashingGraphics
void FlashingGraphics(int Caller, TDateTime Now)
Deal with any warning graphics that need to flash (call on, signal stop, crash etc),...
Definition: InterfaceUnit.cpp:15001
TInterface::ScreenLeftButton
TBitBtn * ScreenLeftButton
Definition: InterfaceUnit.h:250
TTrain::StoppedAtLocation
bool StoppedAtLocation
Definition: TrainUnit.h:432
TTrainController::TContinuationTrainExpectationMultiMapIterator
TContinuationTrainExpectationMultiMap::iterator TContinuationTrainExpectationMultiMapIterator
iterator for the multimap
Definition: TrainUnit.h:689
TInterface::TTClockx16ButtonClick
void __fastcall TTClockx16ButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11777
TInterface::BuildTrackMenuItem
TMenuItem * BuildTrackMenuItem
Definition: InterfaceUnit.h:420
TInterface::SaveOperatingImageMenuItem
TMenuItem * SaveOperatingImageMenuItem
Definition: InterfaceUnit.h:454
TTrainController::StopTTClockFlag
bool StopTTClockFlag
when true the timetable clock is stopped, used for messages display and train popup menu display etc
Definition: TrainUnit.h:731
TInterface::NoRailway
bool NoRailway()
Returns true if there are no track elements and no text.
Definition: InterfaceUnit.cpp:18403
TInterface::AllEntriesTTListBox
TListBox * AllEntriesTTListBox
the list of service entries displayed on the left hand side of the timetable edit screen
Definition: InterfaceUnit.h:404
TInterface::CallingOnButtonClick
void __fastcall CallingOnButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8358
TInterface::SaveTTDialog
TSaveDialog * SaveTTDialog
Definition: InterfaceUnit.h:495
TInterface::DeleteOnePrefDirButtonClick
void __fastcall DeleteOnePrefDirButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1966
TTrack::WriteOperatingTrackToImage
void WriteOperatingTrackToImage(int Caller, Graphics::TBitmap *Bitmap)
Called by TInterface::SaveOperatingImage1Click to add all track element graphics to the image file in...
Definition: TrackUnit.cpp:3733
TAllRoutes::NextRouteID
int NextRouteID
stores the value for the route ID number that is next to be built
Definition: TrackUnit.h:1582
TUtilities::CheckAndReadFileString
bool CheckAndReadFileString(std::ifstream &InFile, AnsiString &OutString)
checks that the value is a string ('0' or CR accepted as delimiters), returns true for success and re...
Definition: Utilities.cpp:468
TInterface::TTEntryChangedFlag
bool TTEntryChangedFlag
true when a timetable entry that is displayed in the timetable entry edit window has changed
Definition: InterfaceUnit.h:999
TInterface::HighlightPanel
TPanel * HighlightPanel
the orange bar that displays the current timetable entry in AllEntriesTTListBox
Definition: InterfaceUnit.h:370
TInterface::SpeedButton16
TSpeedButton * SpeedButton16
Definition: InterfaceUnit.h:520
TInterface::MoveTTEntryUpButtonClick
void __fastcall MoveTTEntryUpButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4243
TInterface::SpeedBottomLabel
TLabel * SpeedBottomLabel
Definition: InterfaceUnit.h:181
TTrainController::BFHigh
bool BFHigh
Definition: TrainUnit.h:743
TUserGraphicItem::FileName
AnsiString FileName
Definition: DisplayUnit.h:33
TInterface::TTClockResetButtonClick
void __fastcall TTClockResetButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11950
TInterface::ClockLabel
TLabel * ClockLabel
the timetable clock
Definition: InterfaceUnit.h:321
TInterface::SpeedButton43
TSpeedButton * SpeedButton43
Definition: InterfaceUnit.h:547
TTrain::LagEntryPos
int LagEntryPos
Definition: TrainUnit.h:327
TInterface::SetTrackBuildImages
void SetTrackBuildImages(int Caller)
Sets the left screen images (track linked or not, gaps set or not, locations named or not) during rai...
Definition: InterfaceUnit.cpp:15815
TTrack::WriteGraphicsToImage
void WriteGraphicsToImage(int Caller, Graphics::TBitmap *Bitmap)
Called by SaveImageNoGridMenuItemClick, SaveImageAndGridMenuItemClick amd SaveImageAndPrefDirsMenuIte...
Definition: TrackUnit.cpp:3711
TInterface::AddText
@ AddText
Definition: InterfaceUnit.h:881
TTrack::PlotPastedTrackElementWithAttributes
void PlotPastedTrackElementWithAttributes(int Caller, TTrackElement TempTrackElement, int HLocInput, int VLocInput, bool &TrackLinkingRequiredFlag, bool InternalChecks)
new at v2.2.0 - as PlotAndAddTrackElement but keeping speed & length attributes (for pasting) and als...
Definition: TrackUnit.cpp:2058
TTrainController::UnexpectedExits
int UnexpectedExits
Definition: TrainUnit.h:779
TInterface::LoadTimetableMenuItemClick
void __fastcall LoadTimetableMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9693
TInterface::LengthEditKeyUp
void __fastcall LengthEditKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:11563
TOnePrefDir::EveryPrefDirMarker
void EveryPrefDirMarker(int Caller, TDisplay *Disp)
Similar to PrefDirMarker but used only to mark EveryPrefDir - red for unidirectional PrefDir & green ...
Definition: TrackUnit.cpp:11320
TInterface::OutputLog1
TLabel * OutputLog1
Definition: InterfaceUnit.h:292
TTrain::LeavingUnderSigControlAtContinuation
bool LeavingUnderSigControlAtContinuation
set when the train has reached an exit continuation when under signaller control, used to prevent the...
Definition: TrainUnit.h:355
TInterface::SpeedButton84
TSpeedButton * SpeedButton84
Definition: InterfaceUnit.h:588
TInterface::SpeedButton77
TSpeedButton * SpeedButton77
Definition: InterfaceUnit.h:581
TInterface::SpeedButton128
TSpeedButton * SpeedButton128
Definition: InterfaceUnit.h:632
TTrack::SetTrackFinished
void SetTrackFinished(bool Value)
Definition: TrackUnit.h:845
TTrack::GetInactiveTrackElementFromTrackMap
TTrackElement & GetInactiveTrackElementFromTrackMap(int Caller, int HLoc, int VLoc)
Return a reference to the inactive element at HLoc & VLoc, if no element is found an error is thrown.
Definition: TrackUnit.cpp:5130
TInterface::AddSubMinsBox
TEdit * AddSubMinsBox
the edit box that accepts minutes to add or subtract
Definition: InterfaceUnit.h:175
TAllRoutes::LoadRoutes
bool LoadRoutes(int Caller, std::ifstream &InFile)
Loads the routes from a session file.
Definition: TrackUnit.cpp:17681
TInterface::TTClockExitButton
TButton * TTClockExitButton
Definition: InterfaceUnit.h:218
TInterface::SpeedEditBox2
TEdit * SpeedEditBox2
Definition: InterfaceUnit.h:101
TInterface::MoveForwardsMenuItemClick
void __fastcall MoveForwardsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9979
TTrack::Down
@ Down
Definition: TrackUnit.h:523
TTrainController::TwoOrMoreLocationsWarningGiven
bool TwoOrMoreLocationsWarningGiven
new at v2.6.0 to allow loops
Definition: TrainUnit.h:739
TInterface::TimetableNameLabel
TLabel * TimetableNameLabel
displays the current timetable name on the timetable edit panel
Definition: InterfaceUnit.h:311
TInterface::SpeedButton79
TSpeedButton * SpeedButton79
Definition: InterfaceUnit.h:583
TInterface::SpeedBottomLabel2
TLabel * SpeedBottomLabel2
Definition: InterfaceUnit.h:112
TInterface::SpeedButton51
TSpeedButton * SpeedButton51
Definition: InterfaceUnit.h:555
TInterface::IsPerformancePanelObscuringFloatingLabel
bool IsPerformancePanelObscuringFloatingLabel(int Caller)
Checked during operation, returns true if so and PerformancePanel removed - not used from v2....
Definition: InterfaceUnit.cpp:15658
TimeTimeLoc
@ TimeTimeLoc
Definition: TrainUnit.h:62
TOneRoute::ReqPosRouteID
IDInt ReqPosRouteID
session saves as routes in build are not saved in sessions
Definition: TrackUnit.h:1402
TInterface::TimetableChangedInAZOrderFlag
bool TimetableChangedInAZOrderFlag
used to give a warning message that changes will be discarded if proceed
Definition: InterfaceUnit.h:995
TTrack::PlotRaisedLinkedLevelCrossingBarriers
void PlotRaisedLinkedLevelCrossingBarriers(int Caller, int BaseElementSpeedTag, int HLoc, int VLoc, TDisplay *Disp)
Plot & close (to trains) all level crossings linked to TrackElement - always plots as red - auto.
Definition: TrackUnit.cpp:6331
TInterface::AddTrackButtonClick
void __fastcall AddTrackButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:864
TInterface::SpeedButton92
TSpeedButton * SpeedButton92
Definition: InterfaceUnit.h:596
TInterface::DeleteMenuItemClick
void __fastcall DeleteMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9551
TTrain::Derailed
bool Derailed
Definition: TrainUnit.h:432
TInterface::ConflictAnalysisButton
TButton * ConflictAnalysisButton
Definition: InterfaceUnit.h:233
TTextHandler::TextVectorPush
void TextVectorPush(int Caller, TTextItem Text)
push &Text onto TextVector & reset the size of the railway if necessary
Definition: TextUnit.cpp:485
TInterface::TTClockAdjButton
TBitBtn * TTClockAdjButton
Definition: InterfaceUnit.h:204
TInterface::PowerEditBoxKeyUp
void __fastcall PowerEditBoxKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:11430
TOneRoute::TRouteFlash::PlotRouteOriginal
void PlotRouteOriginal(int Caller)
display the original (non route-coloured) graphic
Definition: TrackUnit.cpp:16151
TTrack::ResetLevelCrossings
void ResetLevelCrossings(int Caller)
Set all LC attributes to 0 (closed to trains)
Definition: TrackUnit.cpp:6695
TTrainController::SaveSessionLockedRoutes
void SaveSessionLockedRoutes(int Caller, std::ofstream &SessionFile)
save locked routes to a session file
Definition: TrainUnit.cpp:14111
TInterface::OpenHelpMenuItemClick
void __fastcall OpenHelpMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11199
TTrain::OriginalPowerAtRail
double OriginalPowerAtRail
new at v2.4.0 to store value before a failure so it can be restored from here when repaired
Definition: TrainUnit.h:398
TInterface::CheckPerformanceFile
bool CheckPerformanceFile(int Caller, std::ifstream &InFile)
Check the performance file embedded within a session file & return false for error,...
Definition: InterfaceUnit.cpp:17648
TInterface::TInterface
__fastcall TInterface(TComponent *Owner)
constructor
Definition: InterfaceUnit.cpp:80
TInterface::SpeedButton15
TSpeedButton * SpeedButton15
Definition: InterfaceUnit.h:519
clB4G5R5
#define clB4G5R5
Definition: GraphicUnit.h:244
Timetable
@ Timetable
Definition: TrainUnit.h:56
TUtilities::SaveFileDouble
void SaveFileDouble(std::ofstream &OutFile, double SaveDouble)
converts the double value to a string (if double stored directly it is truncated to 6 digits) then st...
Definition: Utilities.cpp:123
TInterface
Definition: InterfaceUnit.h:56
TInterface::RemoveTrainMenuItemClick
void __fastcall RemoveTrainMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10301
TInterface::RotRightMenuItemClick
void __fastcall RotRightMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9160
TTrain::AbleToMoveButForSignal
bool AbleToMoveButForSignal(int Caller)
Indicates that a train is only prevented from moving by a signal - used to allow appropriate popup me...
Definition: TrainUnit.cpp:6333
TTrainController::OpActionPanelVisible
bool OpActionPanelVisible
new v2.2.0 flag to prevent time to act functions when not visible
Definition: TrainUnit.h:737
TInterface::SaveInterface
void SaveInterface(int Caller, std::ofstream &SessionFile)
Save interface part of a session file.
Definition: InterfaceUnit.cpp:16274
TInterface::AcceptDragging
void __fastcall AcceptDragging(TObject *Sender, TObject *Source, int X, int Y, TDragState State, bool &Accept)
Definition: InterfaceUnit.cpp:5502
Parapet
@ Parapet
Definition: TrackUnit.h:64
TTrack::GapFlashRedPosition
int GapFlashRedPosition
TrackVectorPosition of the gap element that is flashing green or red.
Definition: TrackUnit.h:673
HiddenDisplay
TDisplay * HiddenDisplay
The object pointer for the internal hidden display, object created in InterfaceUnit.
Definition: DisplayUnit.cpp:54
TAllRoutes::GetFixedRouteAt
const TOneRoute & GetFixedRouteAt(int Caller, int At) const
Returns a constant reference to the route at AllRoutesVector position 'At', after performing range ch...
Definition: TrackUnit.cpp:16176
TUtilities::clTransparent
TColor clTransparent
the display background colour, can be white, black or dark blue
Definition: Utilities.h:65
TInterface::RouteFlashDuration
float RouteFlashDuration
duration of the route flash period
Definition: InterfaceUnit.h:1037
TInterface::SpeedButton4
TSpeedButton * SpeedButton4
Definition: InterfaceUnit.h:508
TTrainController::SignalStopWarning
bool SignalStopWarning
Definition: TrainUnit.h:729
TPrefDirElement::GetELinkPos
int GetELinkPos() const
Returns the ELink array position.
Definition: TrackUnit.h:277
TTrack::CheckLocationNameMultiMap
void CheckLocationNameMultiMap(int Caller)
Validity test.
Definition: TrackUnit.cpp:8284
TOneRoute::TRouteFlash::PlotRouteOverlay
void PlotRouteOverlay(int Caller)
display the overlay (route-coloured) graphic
Definition: TrackUnit.cpp:16126
TDisplay::PerformanceLog
void PerformanceLog(int Caller, AnsiString Statement)
Send Statement to the performance log on screen and to the file.
Definition: DisplayUnit.cpp:447
TTrain::SignallerStopBrakeRate
double SignallerStopBrakeRate
the train brake rate when stopping under signaller control
Definition: TrainUnit.h:393
TTrainController::SignallerTrainRemovedOnAutoSigsRoute
bool SignallerTrainRemovedOnAutoSigsRoute
true if train was on an AutoSigsRoute when removed by the signaller
Definition: TrainUnit.h:735
TTrack::InactiveTrackVector
TTrackVector InactiveTrackVector
Definition: TrackUnit.h:710
TTrainController::MRSLow
bool MRSLow
Definition: TrainUnit.h:743
TTrack::ActiveTrackElementNameMap
TActiveTrackElementNameMap ActiveTrackElementNameMap
map of active track element names
Definition: TrackUnit.h:685
TTrain::Crashed
bool Crashed
Definition: TrainUnit.h:432
TInterface::SpeedButton44
TSpeedButton * SpeedButton44
Definition: InterfaceUnit.h:548
TTrackElement::HLoc
int HLoc
Definition: TrackUnit.h:145
TInterface::ScreenRightButton
TBitBtn * ScreenRightButton
Definition: InterfaceUnit.h:249
TTrain::HeadCodePosition
Graphics::TBitmap * HeadCodePosition[4]
Set from the HeadCodeGrPtr[4] pointer values, HeadCodePosition[0] is always the front,...
Definition: TrainUnit.h:446
TInterface::SigPrefButtonClick
void __fastcall SigPrefButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2091
TInterface::OAListBox
TListBox * OAListBox
Operator action list, sits inside OperatorActionPanel and lists trains in ascending order of time to ...
Definition: InterfaceUnit.h:406
TTrain::TrainID
int TrainID
the train's identification number
Definition: TrainUnit.h:330
TInterface::SaveTTButton
TButton * SaveTTButton
Definition: InterfaceUnit.h:145
TUtilities::CheckStringDouble
bool CheckStringDouble(AnsiString &DoubleString)
checks the string represents a valid double value, returns true for success. Added at v2....
Definition: Utilities.cpp:327
TInterface::SpeedButton63
TSpeedButton * SpeedButton63
Definition: InterfaceUnit.h:567
TRailGraphics::bmLightBlueRect
Graphics::TBitmap * bmLightBlueRect
Definition: GraphicUnit.h:522
TInterface::NonSigRouteStartMarker
TGraphicElement * NonSigRouteStartMarker
Definition: InterfaceUnit.h:1118
clB3G3R3
#define clB3G3R3
Definition: GraphicUnit.h:186
TInterface::SpeedButton53
TSpeedButton * SpeedButton53
Definition: InterfaceUnit.h:557
TInterface::SpeedButton107
TSpeedButton * SpeedButton107
Definition: InterfaceUnit.h:611
TTrainController::TrainVectorAt
TTrain & TrainVectorAt(int Caller, int VecPos)
Return a reference to the train at position VecPos in the TrainVector, carries out range checking on ...
Definition: TrainUnit.cpp:14387
TInterface::EditMenuClick
void __fastcall EditMenuClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8823
TTrackElement::LCPlotted
bool LCPlotted
Utility marker to avoid plotting every element of a multitrack LC during ClearandRebuildRailway.
Definition: TrackUnit.h:135
TOnePrefDir::PrefDirMarker
void PrefDirMarker(int Caller, TPrefDirRoute PrefDirRoute, bool BuildingPrefDir, TDisplay *Disp) const
PrefDir and route track marker, including direction markers.
Definition: TrackUnit.cpp:11247
TInterface::ModeMenu
TMenuItem * ModeMenu
Definition: InterfaceUnit.h:419
TInterface::SpeedButton112
TSpeedButton * SpeedButton112
Definition: InterfaceUnit.h:616
TInterface::MTBFEditBoxClick
void __fastcall MTBFEditBoxClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12261
TInterface::TEVPtr
TTEVPtr TEVPtr
Definition: InterfaceUnit.h:1141
TInterface::MasterClock
TTimer * MasterClock
the program clock (not the timetable clock)
Definition: InterfaceUnit.h:499
TInterface::OutputLog6MouseDown
void __fastcall OutputLog6MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11128
TRailGraphics::SpeedBut70GrndBlackGlyph
Graphics::TBitmap * SpeedBut70GrndBlackGlyph
Definition: GraphicUnit.h:1054
TTrainController::NumFailures
int NumFailures
Definition: TrainUnit.h:780
TInterface::CreateEditTTTitle
AnsiString CreateEditTTTitle
the title of the timetable currently being edited - i.e. the filename without the '....
Definition: InterfaceUnit.h:902
TInterface::AboutMenuItemClick
void __fastcall AboutMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11178
TInterface::SelectStartPair
THVPair SelectStartPair
'Select' menu items
Definition: InterfaceUnit.h:1120
TTrainController::TOpTimeToActMultiMapIterator
TOpTimeToActMultiMap::iterator TOpTimeToActMultiMapIterator
Definition: TrainUnit.h:721
TInterface::SpeedButton6
TSpeedButton * SpeedButton6
Definition: InterfaceUnit.h:510
TTrack
Definition: TrackUnit.h:463
TInterface::OperatorActionPanelStartDrag
void __fastcall OperatorActionPanelStartDrag(TObject *Sender, TDragObject *&DragObject)
Definition: InterfaceUnit.cpp:5577
TTrack::TwoAspectBuild
@ TwoAspectBuild
Definition: TrackUnit.h:757
TInterface::OperateRailwayMenuItem
TMenuItem * OperateRailwayMenuItem
Definition: InterfaceUnit.h:424
TInterface::SaveRailwayTBPButton
TBitBtn * SaveRailwayTBPButton
Save button on TrackBuildPanel.
Definition: InterfaceUnit.h:73
TTrain::ExitSpeedFull
double ExitSpeedFull
speed when leaving the next element
Definition: TrainUnit.h:381
TInterface::MTBFLabel
TLabel * MTBFLabel
Definition: InterfaceUnit.h:482
TInterface::SelectBitmap
Graphics::TBitmap * SelectBitmap
the graphic defined by Edit->Select & Edit->Reselect
Definition: InterfaceUnit.h:1042
TInterface::PreventGapOffsetResetting
bool PreventGapOffsetResetting
during gap setting gaps are highlighted in turn for the user to select the matching gap,...
Definition: InterfaceUnit.h:961
TInterface::TakeSignallerControlMenuItem
TMenuItem * TakeSignallerControlMenuItem
Definition: InterfaceUnit.h:460
clB5G5R5
#define clB5G5R5
Definition: GraphicUnit.h:286
TInterface::Pasting
@ Pasting
Definition: InterfaceUnit.h:882
TInterface::AddTextButton
TBitBtn * AddTextButton
Definition: InterfaceUnit.h:66
TInterface::LoadRailwayMenuItem
TMenuItem * LoadRailwayMenuItem
Definition: InterfaceUnit.h:410
TUtilities::TimeStamp
AnsiString TimeStamp()
creates a string of the form 'hh:mm:ss' for use in call & event logging
Definition: Utilities.cpp:73
TInterface::CrashImage
TImage * CrashImage
Definition: InterfaceUnit.h:263
TTrainController::RandomFailureCounter
unsigned int RandomFailureCounter
new at v2.4.0, resets after 53 seconds (53 prime so can trigger at any clock time)
Definition: TrainUnit.h:795
TInterface::SpeedButton123
TSpeedButton * SpeedButton123
Definition: InterfaceUnit.h:627
TInterface::USERGRAPHICS_DIR_NAME
static const UnicodeString USERGRAPHICS_DIR_NAME
Definition: InterfaceUnit.h:868
TInterface::mbLeftDown
bool mbLeftDown
true when the left mouse button is down
Definition: InterfaceUnit.h:951
TInterface::SpeedButton115
TSpeedButton * SpeedButton115
Definition: InterfaceUnit.h:619
TInterface::ProgramVersion
UnicodeString ProgramVersion
Definition: InterfaceUnit.h:854
TInterface::TTClockResetButton
TButton * TTClockResetButton
Definition: InterfaceUnit.h:219
TUtilities::CheckAndReadFileInt
bool CheckAndReadFileInt(std::ifstream &InFile, int Lowest, int Highest, int &OutInt)
checks that the value is an int lying between Lowest & Highest (inclusive), returns true for success ...
Definition: Utilities.cpp:251
TInterface::TempCursor
TCursor TempCursor
stores the screen cursor while a temporary cursor (ususlly an hourglass) is displayed
Definition: InterfaceUnit.h:1107
Interface
TInterface * Interface
Definition: InterfaceUnit.cpp:67
TInterface::SpeedButton61
TSpeedButton * SpeedButton61
Definition: InterfaceUnit.h:565
TDisplay::HideWarningLog
void HideWarningLog(int Caller)
Hide all the warnings from the top part of the screen - for timetable clock adjustment.
Definition: DisplayUnit.cpp:475
TTrackElement::ActiveTrackElementName
AnsiString ActiveTrackElementName
Location name used either in the timetable or for a continuation (continuation names not used in time...
Definition: TrackUnit.h:126
TUtilities::DecimalPoint
char DecimalPoint
added at v2.4.0 so can use the local value in loaded session files
Definition: Utilities.h:45
TInterface::ConstructPrefDir
TOnePrefDir * ConstructPrefDir
the Pref Dir under construction
Definition: InterfaceUnit.h:1127
TInterface::SpeedButton81
TSpeedButton * SpeedButton81
Definition: InterfaceUnit.h:585
TInterface::SigsOnLeftImage1
TImage * SigsOnLeftImage1
Definition: InterfaceUnit.h:280
TInterface::BuildTrackMenuItemClick
void __fastcall BuildTrackMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:847
TTrack::LoadTrack
void LoadTrack(int Caller, std::ifstream &VecFile, bool &GraphicsFollow)
Load track elements (active & inactive) from the file into the relevant vectors and maps,...
Definition: TrackUnit.cpp:2596
TInterface::ClearandRebuildRailway
void ClearandRebuildRailway(int Caller)
Clear screen and rebuild it from stored data, uses HiddenScreen to avoid flicker.
Definition: InterfaceUnit.cpp:12479
TInterface::DisplayOneTTLineInPanel
void DisplayOneTTLineInPanel(int Caller, AnsiString Data, bool ServiceEntry)
Display a line from the TimetableEditVector (consists of a series of AnsiStrings, each of which repre...
Definition: InterfaceUnit.cpp:5282
TInterface::PlanPrefDirsMenuItem
TMenuItem * PlanPrefDirsMenuItem
Definition: InterfaceUnit.h:421
TInterface::AreAnyTimesInCurrentEntry
bool AreAnyTimesInCurrentEntry()
Search the timetable entry pointed to by TTCurrentEntryPtr and if any times (HH:MM) are present retur...
Definition: InterfaceUnit.cpp:5362
TTrainController::LogEvent
void LogEvent(AnsiString Str)
store Str to the event log - moved from TUtilities for v0.6 so can record the tt clock value
Definition: TrainUnit.cpp:7969
TInterface::AutoRouteStartMarker
TGraphicElement * AutoRouteStartMarker
Definition: InterfaceUnit.h:1118
TInterface::RestoreTTButtonClick
void __fastcall RestoreTTButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4404
TInterface::SaveTTButtonClick
void __fastcall SaveTTButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4022
TInterface::FormCreate
void __fastcall FormCreate(TObject *Sender)
Definition: InterfaceUnit.cpp:743
TGraphicElement::SetSourceRect
void SetSourceRect(int Left, int Top)
Set SourceRect member values from those supplied and existing Width & Height - ensure this is only ca...
Definition: TrackUnit.h:373
TTrack::SelectPush
void SelectPush(TTrackElement TrackElement)
Store a TrackElement in the SelectVector.
Definition: TrackUnit.h:824
TAllRoutes::SignallerRemovedTrainAutoRoute
TOneRoute SignallerRemovedTrainAutoRoute
if train was on an AutoSigsRoute when removed then this stores the route so that signals can be reset
Definition: TrackUnit.h:1588
TInterface::SpeedButton7
TSpeedButton * SpeedButton7
Definition: InterfaceUnit.h:511
TTrainController::MassHigh
bool MassHigh
Definition: TrainUnit.h:743
TInterface::TimetablePanel
TPanel * TimetablePanel
'Create a timetable'/'Edit a timetable' panel that contains the topmost buttons (show/hide & exit)
Definition: InterfaceUnit.h:361
TTrack::PlotAndAddTrackElement
void PlotAndAddTrackElement(int Caller, int CurrentTag, int Aspect, int HLocInput, int VLocInput, bool &TrackPlottedFlag, bool InternalChecks)
Called during track building or pasting, when an element identified by CurrentTag (i....
Definition: TrackUnit.cpp:1823
TTrain::PlotTrainWithNewBackgroundColour
void PlotTrainWithNewBackgroundColour(int Caller, TColor NewBackgroundColour, TDisplay *Disp)
Changes the train's background colour (e.g. to pale green if stopped at a station) Note that this use...
Definition: TrainUnit.cpp:3263
TInterface::LoadSessionMenuItem
TMenuItem * LoadSessionMenuItem
Definition: InterfaceUnit.h:414
TInterface::SpeedButton69
TSpeedButton * SpeedButton69
Definition: InterfaceUnit.h:573
TUtilities::SaveFileString
void SaveFileString(std::ofstream &OutFile, AnsiString SaveString)
stores the string value to the file, then a '0' delimiter then a CR
Definition: Utilities.cpp:131
TInterface::OutputLog5MouseDown
void __fastcall OutputLog5MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11119
TInterface::ErrorButton
TBitBtn * ErrorButton
the 'Press to exit' button on the error screen
Definition: InterfaceUnit.h:257
TInterface::SpeedButton24
TSpeedButton * SpeedButton24
Definition: InterfaceUnit.h:528
TInterface::WarningFlash
bool WarningFlash
toggles on and off automatically at a cycle of about 0.5 sec, used to drive the warning icons during ...
Definition: InterfaceUnit.h:1001
TInterface::CurrentSpeedButton
TSpeedButton * CurrentSpeedButton
stores the selected track build element button during railway building
Definition: InterfaceUnit.h:1138
TInterface::MainScreenMouseDown
void __fastcall MainScreenMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:5598
TTrain::ExitTimeFull
TDateTime ExitTimeFull
times used in SetTrainMovementValues corresponding to the next element the train runs on
Definition: TrainUnit.h:414
TTrackElement::TwoAspect
@ TwoAspect
Definition: TrackUnit.h:156
TTrack::GapFlashRed
TGraphicElement * GapFlashRed
the red & green circle graphics used to show where the gaps are
Definition: TrackUnit.h:693
TInterface::TotalTicks
unsigned int TotalTicks
total clock ticks
Definition: InterfaceUnit.h:1048
TTrack::TryToConnectTrack
bool TryToConnectTrack(int Caller, bool &LocError, int &HLoc, int &VLoc, bool GiveMessages)
Handles all tasks associated with track linking, returns true if successful (see also LinkTrack & Lin...
Definition: TrackUnit.cpp:2281
TInterface::SpeedTopLabel2
TLabel * SpeedTopLabel2
Definition: InterfaceUnit.h:111
SignallerChangeDirection
@ SignallerChangeDirection
Definition: TrainUnit.h:51
TRailGraphics::GridBitmap
Graphics::TBitmap * GridBitmap
Definition: GraphicUnit.h:899
TInterface::PowerBottomLabel
TLabel * PowerBottomLabel
Definition: InterfaceUnit.h:189
TInterface::PasteMenuItem
TMenuItem * PasteMenuItem
Definition: InterfaceUnit.h:437
TTextHandler::EnterAndDisplayNewText
void EnterAndDisplayNewText(int Caller, TTextItem Text, int HPos, int VPos)
add Text to TextVector and display it on the screen
Definition: TextUnit.cpp:179
TOnePrefDir::EndPossible
bool EndPossible(int Caller, bool &LeadingPoints)
Used when setting preferred directions, true if able to finish at the last selected element (can't fi...
Definition: TrackUnit.cpp:11035
TInterface::CreateEditTTFileName
AnsiString CreateEditTTFileName
the full path and filename of the timetable file
Definition: InterfaceUnit.h:900
TOnePrefDir::ConsolidatePrefDirs
void ConsolidatePrefDirs(int Caller, TOnePrefDir *InputPrefDir)
Used when a preferred direction has been set to add all the elements to EveryPrefDir,...
Definition: TrackUnit.cpp:11792
TInterface::PerformanceLogButtonClick
void __fastcall PerformanceLogButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2187
TTrainController::CheckSessionContinuationAutoSigEntries
bool CheckSessionContinuationAutoSigEntries(int Caller, std::ifstream &SessionFile)
Part of the session file integrity check for ContinuationAutoSigEntries, true for success.
Definition: TrainUnit.cpp:14233
IDInt
Definition: TrackUnit.h:412
TInterface::SelectLengthsMenuItemClick
void __fastcall SelectLengthsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9570
TInterface::NewSelectBitmapHLoc
int NewSelectBitmapHLoc
the new (during & at end of moving) HLoc value of Edit->Select & Edit->Reselect
Definition: InterfaceUnit.h:1056
TInterface::LoadUserGraphic
void LoadUserGraphic(int Caller)
Load a user-defined graphic (bmp, gif, jpg, png).
Definition: InterfaceUnit.cpp:18630
TInterface::TTCurrentEntryPtr
TTEVPtr TTCurrentEntryPtr
Definition: InterfaceUnit.h:1141
TRunningEntry
TRunningEntry
contains status info for each train
Definition: TrainUnit.h:79
TInterface::OutputLog6
TLabel * OutputLog6
Definition: InterfaceUnit.h:297
TUtilities
Definition: Utilities.h:36
TTrack::FindAndHighlightAnUnsetGap
bool FindAndHighlightAnUnsetGap(int Caller)
True if there is an unset gap, and if so it is marked with a red circle, used during gap setting.
Definition: TrackUnit.cpp:3980
TInterface::CreateTimetableMenuItemClick
void __fastcall CreateTimetableMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3060
TInterface::ExportTTButtonClick
void __fastcall ExportTTButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4487
TDisplay
Definition: DisplayUnit.h:48
TInterface::SpeedButton9
TSpeedButton * SpeedButton9
Definition: InterfaceUnit.h:513
TInterface::TTClockxEighthButtonClick
void __fastcall TTClockxEighthButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11853
TTrack::PlotSmallRailway
void PlotSmallRailway(int Caller, TDisplay *Disp)
Plot on screen the zoomed-out railway.
Definition: TrackUnit.cpp:9265
TTrackElement::ConnLinkPos
int ConnLinkPos[4]
Connecting element link position (i.e. array positions of the connecting element links,...
Definition: TrackUnit.h:143
TTrainController::ContinuationAutoSigVector
TContinuationAutoSigVector ContinuationAutoSigVector
vector for TContinuationAutoSigEntry objects
Definition: TrainUnit.h:797
TInterface::Text_X
int Text_X
the 'X' pixel value for an item of text
Definition: InterfaceUnit.h:1090
TInterface::SpeedVariableLabel
TLabel * SpeedVariableLabel
Definition: InterfaceUnit.h:182
TInterface::SpeedButton49
TSpeedButton * SpeedButton49
Definition: InterfaceUnit.h:553
TTrain::StoppedWithoutPower
bool StoppedWithoutPower
Definition: TrainUnit.h:433
TInterface::PowerVariableLabel
TLabel * PowerVariableLabel
Definition: InterfaceUnit.h:190
TActionEventType
TActionEventType
Used for reporting error conditions & warnings.
Definition: TrainUnit.h:39
TInterface::GapsNotSetImage
TImage * GapsNotSetImage
Definition: InterfaceUnit.h:277
TInterface::Level1Mode
enum TInterface::TLevel1Mode Level1Mode
TInterface::CallLogTickerLabel
TLabel * CallLogTickerLabel
diagnostic label displaying the call log depth, made visible by ctrl+ alt+ 2
Definition: InterfaceUnit.h:319
TInterface::TimetableEditVector
TTimetableEditVector TimetableEditVector
Definition: InterfaceUnit.h:1144
TTrainController::TrainExistsAtIdent
bool TrainExistsAtIdent(int Caller, int TrainID)
new at v2.4.0 return true if find the train (added at v2.4.0 as can select a removed train in OAListB...
Definition: TrainUnit.cpp:8669
SignallerJoin
@ SignallerJoin
Definition: TrainUnit.h:50
TTrain::StepForwardFlag
bool StepForwardFlag
set when the signaller command to step forward one element has been given
Definition: TrainUnit.h:365
TInterface::SaveRailwayDialog
TSaveDialog * SaveRailwayDialog
Definition: InterfaceUnit.h:494
TInterface::TTClockAdjustWarningPanel
TPanel * TTClockAdjustWarningPanel
Definition: InterfaceUnit.h:213
TInterface::TrainTTInfoOnOffMenuItemClick
void __fastcall TrainTTInfoOnOffMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:5477
TFixedTrackPiece::Config
TConfiguration Config[4]
the type of link - see TConfiguration above
Definition: TrackUnit.h:95
TTrainController::Operate
void Operate(int Caller)
called every clock tick to introduce new trains and update existing trains
Definition: TrainUnit.cpp:7981
TTrackElement::TrainIDOnElement
int TrainIDOnElement
Definition: TrackUnit.h:151
TRailGraphics::smRed
Graphics::TBitmap * smRed
Definition: GraphicUnit.h:885
TTrain::PowerAtRail
double PowerAtRail
in Watts (taken as 80% of the train's Gross Power, i.e. that entered by the user)
Definition: TrainUnit.h:396
TTrack::FlipArray
int FlipArray[FirstUnusedSpeedTagNumber]
holds TrackElement SpeedTag values for 'flipping' via menu items 'Edit' & 'Flip'
Definition: TrackUnit.h:671
TAllRoutes::LevelCrossingBarrierDownDelay
const float LevelCrossingBarrierDownDelay
the full value in seconds for which the level crossing flashes prior to opening to trains
Definition: TrackUnit.h:1576
TAllRoutes::RebuildRailwayFlag
bool RebuildRailwayFlag
this is set whenever a route has to be cancelled forcibly in order to force a ClearandRebuildRailway ...
Definition: TrackUnit.h:1569
TUtilities::LoadFileInt
int LoadFileInt(std::ifstream &InFile)
loads an int value from the file
Definition: Utilities.cpp:154
TInterface::SetSaveMenuAndButtons
void SetSaveMenuAndButtons(int Caller)
Called during the ClockTimer2 function to set screen boundaries, buttons & menu items.
Definition: InterfaceUnit.cpp:15283
TTrack::SignalAspectBuildMode
enum TTrack::@2 SignalAspectBuildMode
aspect mode for future signal additions
TInterface::TIMETABLE_DIR_NAME
static const UnicodeString TIMETABLE_DIR_NAME
Definition: InterfaceUnit.h:863
TTrackElement::ElementID
AnsiString ElementID
the element identifier based on position in the railway
Definition: TrackUnit.h:128
TInterface::SaveImageAndPrefDirsMenuItem
TMenuItem * SaveImageAndPrefDirsMenuItem
Definition: InterfaceUnit.h:453
TInterface::LoadRailwayMenuItemClick
void __fastcall LoadRailwayMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2272
TTrack::CheckMapAndInactiveTrack
void CheckMapAndInactiveTrack(int Caller)
Validity test.
Definition: TrackUnit.cpp:6939
TInterface::FormKeyUp
void __fastcall FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
Definition: InterfaceUnit.cpp:11069
TInterface::CopyTTEntryKeyFlag
bool CopyTTEntryKeyFlag
Definition: InterfaceUnit.h:1016
TTrainDataEntry::TrainOperatingDataVector
TTrainOperatingDataVector TrainOperatingDataVector
operating information for the train including all its repeats
Definition: TrainUnit.h:197
TInterface::OutputLog9MouseDown
void __fastcall OutputLog9MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11158
TTrack::TActiveLevelCrossing::StartTime
TDateTime StartTime
stores the starting time for level crossing changing
Definition: TrackUnit.h:544
TTrackElement::VLoc
int VLoc
The h & v locations in the railway (top lh corner of the first build screen = 0,0)
Definition: TrackUnit.h:145
TTrack::GetNonPointsOppositeLinkPos
int GetNonPointsOppositeLinkPos(int LinkPosIn)
Return the corresponding link position (track always occupies either links 0 & 1 or 2 & 3)
Definition: TrackUnit.h:791
TOneRoute::TRouteFlash::RouteFlashVector
std::vector< TRouteFlashElement > RouteFlashVector
Definition: TrackUnit.h:1388
TInterface::SpeedButton80
TSpeedButton * SpeedButton80
Definition: InterfaceUnit.h:584
TTrain::IsThereAnAdjacentTrain
bool IsThereAnAdjacentTrain(int Caller, TTrain *&TrainToBeJoinedBy)
Definition: TrainUnit.cpp:4712
TInterface::ApproachLocking
void ApproachLocking(int Caller, TDateTime Now)
Function that deals with approach locking during ClockTimer2 function.
Definition: InterfaceUnit.cpp:14256
TInterface::TimetableTitle
AnsiString TimetableTitle
the titles of the loaded railway and loaded timetable, i.e. the filenames without the extension
Definition: InterfaceUnit.h:914
TInterface::BlackBgndMenuItemClick
void __fastcall BlackBgndMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11222
TInterface::SpeedButton114
TSpeedButton * SpeedButton114
Definition: InterfaceUnit.h:618
TInterface::Deleting
@ Deleting
Definition: InterfaceUnit.h:882
TInterface::RestoreAllDefaultLengthsButton
TBitBtn * RestoreAllDefaultLengthsButton
Definition: InterfaceUnit.h:77
TInterface::ClearAllMenuItemClick
void __fastcall ClearAllMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2989
TUtilities::EventLog
std::deque< AnsiString > EventLog
event store, saved to the errorlog for diagnostic purposes
Definition: Utilities.h:57
TInterface::MoveTTEntryUpKeyFlag
bool MoveTTEntryUpKeyFlag
Definition: InterfaceUnit.h:1014
TActionVectorEntry::FormatType
TTimetableFormatType FormatType
defines the timetable action type
Definition: TrainUnit.h:110
TInterface::TextBox
TEdit * TextBox
the edit box that accepts text to be added
Definition: InterfaceUnit.h:88
TGraphicElement::GetHPos
int GetHPos()
Definition: TrackUnit.h:362
TInterface::SpeedButton133
TSpeedButton * SpeedButton133
Definition: InterfaceUnit.h:637
TOnePrefDir::SearchVectorSize
unsigned int SearchVectorSize() const
Return the vector size.
Definition: TrackUnit.h:1281
TTrainController::RestartTime
TDateTime RestartTime
TTClockTime when operation pauses ( = timetable start time prior to operation) TTClockTime is calcula...
Definition: TrainUnit.h:644
TTrainController::TimetableStartTime
TDateTime TimetableStartTime
the start time of the current timetable
Definition: TrainUnit.h:642
TTrainController::UnplotTrains
void UnplotTrains(int Caller)
unplot all trains from screen
Definition: TrainUnit.cpp:8324
TInterface::SpeedButton18
TSpeedButton * SpeedButton18
Definition: InterfaceUnit.h:522
TInterface::ScreenGridFlag
bool ScreenGridFlag
true when the screen grid is displayed
Definition: InterfaceUnit.h:969
TInterface::InfoCaptionStore
AnsiString InfoCaptionStore
temporary store for the information panel caption
Definition: InterfaceUnit.h:908
TRailGraphics::smBrightGreen
Graphics::TBitmap * smBrightGreen
Definition: GraphicUnit.h:877
TInterface::CopiedEntryFlag
bool CopiedEntryFlag
true when CopiedEntryStr holds a timetable entry in the timetable editor
Definition: InterfaceUnit.h:931
TOneRoute::ConvertAndAddPreferredRouteSearchVector
void ConvertAndAddPreferredRouteSearchVector(int Caller, IDInt ReqPosRouteID, bool AutoSigsFlag)
Called after a preferred (i.e. preferred direction or automatic signals) route has been selected and ...
Definition: TrackUnit.cpp:14147
TInterface::SpeedButton89
TSpeedButton * SpeedButton89
Definition: InterfaceUnit.h:593
TTrainController::EarlyArrivals
int EarlyArrivals
Definition: TrainUnit.h:765
TInterface::AnyTTKeyFlagSet
bool AnyTTKeyFlagSet()
Definition: InterfaceUnit.h:1154
TTrainController::CreateFormattedTimetable
void CreateFormattedTimetable(int Caller, AnsiString RailwayTitle, AnsiString TimetableTitle, AnsiString CurDir)
Examines the internal timetable (TrainDataVector) and creates from it a chronological (....
Definition: TrainUnit.cpp:14400
TInterface::SetTopIndex
void SetTopIndex(int Caller)
This used in timetable functions when shift keys pressed to make sure that the highlighted entry rema...
Definition: InterfaceUnit.cpp:12457
TTrack::RouteFlashFlag
bool RouteFlashFlag
true while a route is flashing prior to being set
Definition: TrackUnit.h:660
TOnePrefDir::RealignAfterTrackErase
void RealignAfterTrackErase(int Caller, int ErasedTrackVectorPosition)
After a track element is erased the preferred direction elements are likely to be affected....
Definition: TrackUnit.cpp:12251
TInterface::PowerToggleButtonClick
void __fastcall PowerToggleButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11409
PrefDirCall
@ PrefDirCall
Definition: TrackUnit.h:1186
TTrackElement::StationEntryStopLinkPos1
int StationEntryStopLinkPos1
Definition: TrackUnit.h:149
TInterface::SpeedButton46
TSpeedButton * SpeedButton46
Definition: InterfaceUnit.h:550
Points
@ Points
Definition: TrackUnit.h:63
TTrainController::TotLatePassMins
float TotLatePassMins
Definition: TrainUnit.h:760
TTrainController::StripSpaces
void StripSpaces(int Caller, AnsiString &Input)
Strip both leading and trailing spaces at ends of Input and spaces before and after all commas and se...
Definition: TrainUnit.cpp:12797
TInterface::Delay
void Delay(int Caller, double Msec)
Delays operation for the set time in milliseconds.
Definition: InterfaceUnit.cpp:12862
TTrain::JoinedOtherTrainFlag
bool JoinedOtherTrainFlag
true when the train has joined another train following an 'Fjo' timetable command or a signaller join...
Definition: TrainUnit.h:351
TTrainController::OpActionPanelHintDelayCounter
unsigned int OpActionPanelHintDelayCounter
new v2.2.0 on start operation delays the op action panel headcode display for about 3 secs while hint...
Definition: TrainUnit.h:793
TTrainController::BFLow
bool BFLow
Definition: TrainUnit.h:743
TInterface::OutputLog7
TLabel * OutputLog7
Definition: InterfaceUnit.h:298
TTrainController::TotArrDepPass
int TotArrDepPass
Definition: TrainUnit.h:778
TInterface::LastNonCtrlOrShiftKeyDown
int LastNonCtrlOrShiftKeyDown
value of last key (other than Ctrl or Shift) pressed down - to prevent repeated FormKeyDown calls fro...
Definition: InterfaceUnit.h:1054
SignallerPassRedSignal
@ SignallerPassRedSignal
Definition: TrainUnit.h:51
TRailGraphics::ChangeForegroundColour
void ChangeForegroundColour(int Caller, Graphics::TBitmap *BitmapIn, Graphics::TBitmap *BitmapOut, TColor NewForegroundColour, TColor BackgroundColour)
Definition: GraphicUnit.cpp:3326
TInterface::TextItem
int TextItem
used to store a single item of text
Definition: InterfaceUnit.h:1096
TInterface::UserGraphicButtonClick
void __fastcall UserGraphicButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12283
TInterface::OriginalTimetableEditVector
TTimetableEditVector OriginalTimetableEditVector
the complete timetable as a list of AnsiStrings for use in edit timetable functions
Definition: InterfaceUnit.h:1144
TGraphicElement::LoadOverlayGraphic
void LoadOverlayGraphic(int Caller, Graphics::TBitmap *Overlay)
Load the temporary overlay graphic.
Definition: TrackUnit.cpp:1569
TInterface::PresetAutoSigRoutesButtonClick
void __fastcall PresetAutoSigRoutesButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11991
TRailGraphics::SpeedBut68GrndBlackGlyph
Graphics::TBitmap * SpeedBut68GrndBlackGlyph
Definition: GraphicUnit.h:1052
TTrain::SignallerRemoved
bool SignallerRemoved
set when removed under signaller control to force a removal from the display at the next clock tick
Definition: TrainUnit.h:359
TTrain::FrontCodePtr
Graphics::TBitmap * FrontCodePtr
points to the front headcode segment, this is set to red or blue depending on TrainMode
Definition: TrainUnit.h:450
TOneRoute::SetRouteSignals
void SetRouteSignals(int Caller) const
Called when setting a route to set all points appropriately. Also called when a new train is added at...
Definition: TrackUnit.cpp:15486
Continuation
@ Continuation
Definition: TrackUnit.h:63
TInterface::ScreenUpButton
TBitBtn * ScreenUpButton
Definition: InterfaceUnit.h:251
TInterface::TTServiceSyntaxCheckButton
TButton * TTServiceSyntaxCheckButton
Definition: InterfaceUnit.h:143
TTrainController::CallOnWarning
bool CallOnWarning
Definition: TrainUnit.h:729
TInterface::SetLengthsButton
TBitBtn * SetLengthsButton
Definition: InterfaceUnit.h:71
TUserGraphicItem::Height
int Height
Definition: DisplayUnit.h:35
GraphicUnit.h
TInterface::AppActivate
void __fastcall AppActivate(TObject *Sender)
Definition: InterfaceUnit.cpp:794
TTrack::RebuildTrackAndText
void RebuildTrackAndText(int Caller, TDisplay *Disp, bool BothPointFilletsAndBasicLCs)
Called by TInterface::ClearandRebuildRailway to replot all the active and inactive track elements and...
Definition: TrackUnit.cpp:3341
TextUnit.h
TTrack::PlotPoints
void PlotPoints(int Caller, TTrackElement TrackElement, TDisplay *Disp, bool BothFillets)
Plot points on screen according to how they are set (Attribute value), or, with both fillets if BothF...
Definition: TrackUnit.cpp:5366
TInterface::AddTextButtonClick
void __fastcall AddTextButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1055
TDisplay::DisplayZoomOutOffsetV
static int DisplayZoomOutOffsetV
the verticalal offset of the zoomed-out display
Definition: DisplayUnit.h:86
TInterface::ReselectMenuItemClick
void __fastcall ReselectMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8871
TInterface::SpeedButton94
TSpeedButton * SpeedButton94
Definition: InterfaceUnit.h:598
TInterface::SaveTTAsKeyFlag
bool SaveTTAsKeyFlag
Definition: InterfaceUnit.h:1025
TInterface::SaveTTEntryButtonClick
void __fastcall SaveTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3874
TInterface::TimetablePanelLabel
TLabel * TimetablePanelLabel
label to the left of TimetablePanel
Definition: InterfaceUnit.h:313
TTrack::PointFlashFlag
bool PointFlashFlag
true when points are flashing during manual change
Definition: TrackUnit.h:658
TTrainController::OnTimeDeps
int OnTimeDeps
Definition: TrainUnit.h:773
TTrain::RestoreTimetableLocation
AnsiString RestoreTimetableLocation
stores the location name at which signaller control is taken, to ensure that it is back at that locat...
Definition: TrainUnit.h:424
TInterface::SpeedButton40
TSpeedButton * SpeedButton40
Definition: InterfaceUnit.h:544
TTrainController::TimetableIntegrityCheck
bool TimetableIntegrityCheck(int Caller, char *FileName, bool GiveMessages, bool CheckLocationsExistInRailway)
Checks overall timetable integrity, calls many other specific checking functions, returns true for su...
Definition: TrainUnit.cpp:9016
AllRoutes
TAllRoutes * AllRoutes
the object pointer, object created in InterfaceUnit
Definition: TrackUnit.cpp:54
TDisplay::Left
int Left()
Return the left pixel position of the screen.
Definition: DisplayUnit.h:114
TTrain::SignallerMaxSpeed
int SignallerMaxSpeed
maximum train speed under signaller control (in km/h)
Definition: TrainUnit.h:323
TInterface::BufferAttentionImage
TImage * BufferAttentionImage
Definition: InterfaceUnit.h:261
TOnePrefDir::ValidatePrefDir
bool ValidatePrefDir(int Caller)
Checks that all elements in PrefDirVector have been properly set, i.e. don't have their default value...
Definition: TrackUnit.cpp:11078
TTrainController::SendPerformanceSummary
void SendPerformanceSummary(int Caller, std::ofstream &PerfFile)
At the end of operation a summary of overall performance is sent to the performance file by this func...
Definition: TrainUnit.cpp:16968
TInterface::OperatorActionButtonClick
void __fastcall OperatorActionButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12095
TInterface::SpeedEditBox
TEdit * SpeedEditBox
Definition: InterfaceUnit.h:179
TInterface::LoadRailwayDialog
TOpenDialog * LoadRailwayDialog
Definition: InterfaceUnit.h:488
TInterface::CopyMenuItem
TMenuItem * CopyMenuItem
Definition: InterfaceUnit.h:433
TInterface::ResetDefaultLengthButtonClick
void __fastcall ResetDefaultLengthButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1565
RepairFailedTrain
@ RepairFailedTrain
Definition: TrainUnit.h:51
TInterface::NoOperMode
@ NoOperMode
Definition: InterfaceUnit.h:873
TInterface::ErrorLogCalledFlag
bool ErrorLogCalledFlag
true when an error has been thrown, stops repeated calls to ErrorLog and stops the MasterClockTimer f...
Definition: InterfaceUnit.h:939
TInterface::NextTTEntryKeyFlag
bool NextTTEntryKeyFlag
Definition: InterfaceUnit.h:1013
TInterface::RouteFlashStartTime
TDateTime RouteFlashStartTime
stores the starting time (timetable clock time) for route flashing
Definition: InterfaceUnit.h:1114
TInterface::PerformancePanelLabel
TLabel * PerformancePanelLabel
label at the top of PerformancePanel
Definition: InterfaceUnit.h:303
TInterface::BlueBgndMenuItemClick
void __fastcall BlueBgndMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11274
TInterface::SetTrackLengths
void SetTrackLengths(int Caller, int Distance, int SpeedLimit)
Called during track building when setting distances, to calculate and set the individual track elemen...
Definition: InterfaceUnit.cpp:18071
TInterface::SpeedToggleButtonClick
void __fastcall SpeedToggleButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11300
TTrainController::ContinuationEntryFloatingTTString
AnsiString ContinuationEntryFloatingTTString(int Caller, TTrainDataEntry *TTDEPtr, int RepeatNumber, int IncrementalMinutes, int IncrementalDigits)
Build string for use in floating window for expected trains at continuations.
Definition: TrainUnit.cpp:8700
TTrack::CheckTrackElementsInFile
bool CheckTrackElementsInFile(int Caller, int &NumberOfActiveElements, bool &GraphicsFollow, std::ifstream &VecFile)
True if TrackElements in the file are all valid.
Definition: TrackUnit.cpp:2958
TGraphicElement::GetVPos
int GetVPos()
Definition: TrackUnit.h:367
TOneRoute::StartSelectionRouteID
IDInt StartSelectionRouteID
needed for session saves as routes in build are not saved in sessions
Definition: TrackUnit.h:1405
TFixedTrackPiece::SpeedTag
int SpeedTag
The element identification number - corresponds to the relevant SpeedButton->Tag.
Definition: TrackUnit.h:85
TTrain::SPADFlag
bool SPADFlag
set when running past a red signal without permission flags to indicate relevant stop conditions or p...
Definition: TrainUnit.h:430
TInterface::TTLabel5
TLabel * TTLabel5
Definition: InterfaceUnit.h:343
TInterface::HomeButtonClick
void __fastcall HomeButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8754
TInterface::PointFlashStartTime
TDateTime PointFlashStartTime
stores the starting time (timetable clock time) for points flashing
Definition: InterfaceUnit.h:1112
TInterface::TTLabel7
TLabel * TTLabel7
Definition: InterfaceUnit.h:345
TInterface::RailwayWebSiteMenuItemClick
void __fastcall RailwayWebSiteMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11214
TTrain::Stopped
bool Stopped()
True if the train has stopped for any reason.
Definition: TrainUnit.h:614
TInterface::SpeedButton36
TSpeedButton * SpeedButton36
Definition: InterfaceUnit.h:540
TInterface::TTFirstServicePtr
TTEVPtr TTFirstServicePtr
Definition: InterfaceUnit.h:1141
TInterface::ClockTimer2
void ClockTimer2(int Caller)
The main loop, called every clock tick via MasterClockTimer.
Definition: InterfaceUnit.cpp:7758
TInterface::SpeedButton56
TSpeedButton * SpeedButton56
Definition: InterfaceUnit.h:560
TDisplay::PlotDashedRect
void PlotDashedRect(int Caller, TRect Rect)
Plot a dashed rectangle for the area defined by Rect, used when selecting display areas.
Definition: DisplayUnit.cpp:429
TInterface::NewTTEntryButtonClick
void __fastcall NewTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3449
TInterface::LoadSessionMenuItemClick
void __fastcall LoadSessionMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2975
TTrack::SelectVectorClear
void SelectVectorClear()
Definition: TrackUnit.h:829
TInterface::PerformanceFileName
AnsiString PerformanceFileName
full path and filename of the performance file
Definition: InterfaceUnit.h:912
TInterface::AutoSigsButton
TBitBtn * AutoSigsButton
Definition: InterfaceUnit.h:195
TInterface::PopupMenu
TPopupMenu * PopupMenu
Definition: InterfaceUnit.h:485
TInterface::LoadSessionFlag
bool LoadSessionFlag
true when a session load command has been given - implemented at next clock tick
Definition: InterfaceUnit.h:949
TPrefDirElement::GetELink
int GetELink() const
Returns ELink.
Definition: TrackUnit.h:271
TInterface::NoTrackMode
@ NoTrackMode
Definition: InterfaceUnit.h:881
TInterface::TimetableValidFlag
bool TimetableValidFlag
indicates that a 'Validate timetable' button click in the timetable editor has succeeded
Definition: InterfaceUnit.h:993
TInterface::TimetableControlMenuItem
TMenuItem * TimetableControlMenuItem
Definition: InterfaceUnit.h:461
TUtilities::CheckFileDouble
bool CheckFileDouble(std::ifstream &InFile)
checks that the value is a double, returns true for success
Definition: Utilities.cpp:294
TUtilities::PerformanceFile
std::ofstream PerformanceFile
the file where the performance log for a particular period of operation is saved
Definition: Utilities.h:53
TInterface::TTLabel15
TLabel * TTLabel15
Definition: InterfaceUnit.h:352
TInterface::PreferredRoute
bool PreferredRoute
true when AutoSig or preferred route building selected during operation (always same state as ConsecS...
Definition: InterfaceUnit.h:957
TInterface::ConvertCRLFsToCommas
void ConvertCRLFsToCommas(int Caller, AnsiString &ConvStr)
Used in timetable editing functions to convert any CRLFs in intended service entries to commas.
Definition: InterfaceUnit.cpp:5063
TInterface::OutputLog2MouseDown
void __fastcall OutputLog2MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11090
TDisplay::DisplayZoomOutOffsetH
static int DisplayZoomOutOffsetH
the horizontal offset of the zoomed-out display
Definition: DisplayUnit.h:84
TInterface::SpeedButton106
TSpeedButton * SpeedButton106
Definition: InterfaceUnit.h:610
Display
TDisplay * Display
The object pointer for the on-screen display, object created in InterfaceUnit.
Definition: DisplayUnit.cpp:53
TInterface::LoadTimetableFromSessionFile
bool LoadTimetableFromSessionFile(int Caller, std::ifstream &SessionFile)
Loads timetable into memory from a session file, true if successful.
Definition: InterfaceUnit.cpp:16739
TTrack::RotRightArray
int RotRightArray[FirstUnusedSpeedTagNumber]
holds TrackElement SpeedTag values for 'rotating right' via menu items 'Edit' & 'Rotate right'
Definition: TrackUnit.h:677
TInterface::SpeedButton125
TSpeedButton * SpeedButton125
Definition: InterfaceUnit.h:629
TInterface::SpeedButton21
TSpeedButton * SpeedButton21
Definition: InterfaceUnit.h:525
TUtilities::DateTimeStamp
AnsiString DateTimeStamp()
creates a string of the form 'dd/mm/yyyy hh:mm:ss' for use in call & event logging
Definition: Utilities.cpp:67
TTrack::GetVLocMin
int GetVLocMin()
Definition: TrackUnit.h:785
TTrack::ResetPoints
void ResetPoints(int Caller)
Called on exit from operation to reset all points to non-diverging or to left fork (Attribute = 0)
Definition: TrackUnit.cpp:4229
TInterface::SpeedButton64
TSpeedButton * SpeedButton64
Definition: InterfaceUnit.h:568
TInterface::AllEntriesTTListBoxMouseUp
void __fastcall AllEntriesTTListBoxMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:4686
TAllRoutes::AllRoutesSize
unsigned int AllRoutesSize() const
Returns the number of routes in the railway.
Definition: TrackUnit.h:1596
TTrack::DuplicatedLocationName
bool DuplicatedLocationName(int Caller, bool GiveMessage)
examines LocationNameMultiMap and returns true if there are two or more locations with the same name ...
Definition: TrackUnit.cpp:7821
TInterface::FontButton
TBitBtn * FontButton
Definition: InterfaceUnit.h:69
TDisplay::Ellipse
void Ellipse(int Caller, int HPos, int VPos, TColor Col)
Plot an ellipse at the defined position and with the defined colour.
Definition: DisplayUnit.cpp:121
TTrack::LCVector
TLCVector LCVector
vector of level crossing InactiveTrackVector positions
Definition: TrackUnit.h:697
TInterface::NextTTEntryButtonClick
void __fastcall NextTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3371
TUtilities::CheckFileBool
bool CheckFileBool(std::ifstream &InFile)
checks that the value is a bool returns true for success
Definition: Utilities.cpp:198
TInterface::~TInterface
__fastcall ~TInterface()
destructor
Definition: InterfaceUnit.cpp:684
TInterface::CancelTTEntryButtonClick
void __fastcall CancelTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4367
TInterface::TTEVPtr
std::vector< AnsiString >::iterator TTEVPtr
typedef for pointers to entries in edit timetable functions
Definition: InterfaceUnit.h:892
TInterface::SaveHeaderMenu1Click
void __fastcall SaveHeaderMenu1Click(TObject *Sender)
Definition: InterfaceUnit.cpp:2917
TInterface::TTStartTimePtr
TTEVPtr TTStartTimePtr
Definition: InterfaceUnit.h:1141
TTrack::TActiveTrackElementNameMapEntry
std::pair< AnsiString, int > TActiveTrackElementNameMapEntry
Definition: TrackUnit.h:618
TInterface::TTClockAdjPanel
TPanel * TTClockAdjPanel
Definition: InterfaceUnit.h:212
TInterface::BuildTrainDataVectorForLoadFile
bool BuildTrainDataVectorForLoadFile(int Caller, std::ifstream &TTBLFile, bool GiveMessages, bool CheckLocationsExistInRailway, bool SessionFile)
Convert a stored timetable file (either as a stand alone file or within a session file) to a loaded t...
Definition: InterfaceUnit.cpp:16950
TInterface::ConflictPanel
TPanel * ConflictPanel
Definition: InterfaceUnit.h:236
TInterface::CompileAllEntriesMemoAndSetPointers
void CompileAllEntriesMemoAndSetPointers(int Caller)
Used during timetable editing funtions to compile the list of entries into the left hand long entry w...
Definition: InterfaceUnit.cpp:4818
TInterface::CopiedEntryStr
AnsiString CopiedEntryStr
a timetable entry that has been copied
Definition: InterfaceUnit.h:898
TInterface::SpeedButton12
TSpeedButton * SpeedButton12
Definition: InterfaceUnit.h:516
TAllRoutes::SaveRoutes
void SaveRoutes(int Caller, std::ofstream &OutFile)
Save railway route information to a session file or an error file.
Definition: TrackUnit.cpp:17665
TInterface::SelectMenuItem
TMenuItem * SelectMenuItem
Definition: InterfaceUnit.h:430
TInterface::MoveTTEntryDownKeyFlag
bool MoveTTEntryDownKeyFlag
Definition: InterfaceUnit.h:1015
TGraphicElement::PlotOverlay
void PlotOverlay(int Caller, TDisplay *Disp)
Plot the overlay graphic on screen.
Definition: TrackUnit.cpp:1579
TTrack::ResetSignals
void ResetSignals(int Caller)
Called on exit from operation to reset all signals to red (Attribute = 0)
Definition: TrackUnit.cpp:4214
Connection
@ Connection
Definition: TrackUnit.h:73
TInterface::TTTextButtonClick
void __fastcall TTTextButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4526
TTrack::LoadBarriersDownVector
void LoadBarriersDownVector(int Caller, std::ifstream &VecFile)
Load all BarriersDownVector values from SessionFile.
Definition: TrackUnit.cpp:3318
TTrainController::TrainFailedWarning
bool TrainFailedWarning
Flags to enable the relevant warning graphics to flash at the left hand side of the screen.
Definition: TrainUnit.h:729
TAllRoutes::RouteTruncateFlag
bool RouteTruncateFlag
used to flag the fact that a route is being truncated on order to change the behaviour of signal aspe...
Definition: TrackUnit.h:1571
TInterface::LengthOKButton
TBitBtn * LengthOKButton
distance/speed setting buttons - left to right & top to bottom
Definition: InterfaceUnit.h:80
TTrain::NextTrainID
static int NextTrainID
the ID value to be used for the next train that is created, static so that it doesn't need an object ...
Definition: TrainUnit.h:287
TInterface::PreviousTTEntryButtonClick
void __fastcall PreviousTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3410
TInterface::UserGraphicButton
TBitBtn * UserGraphicButton
Definition: InterfaceUnit.h:82
TOneRoute::ConvertAndAddNonPreferredRouteSearchVector
void ConvertAndAddNonPreferredRouteSearchVector(int Caller, IDInt ReqPosRouteID)
Called after a non-preferred (i.e. unrestricted) route has been selected and has finished flashing,...
Definition: TrackUnit.cpp:15296
TInterface::Text_Y
int Text_Y
as above for 'Y'
Definition: InterfaceUnit.h:1092
TAllRoutes::CheckMapAndRoutes
void CheckMapAndRoutes(int Caller)
Diagnostic function - checks equivalence for each route between entries in PrefDirVector and those in...
Definition: TrackUnit.cpp:16967
TInterface::DeleteTTEntryButton
TButton * DeleteTTEntryButton
Definition: InterfaceUnit.h:133
DefaultTrackSpeedLimit
#define DefaultTrackSpeedLimit
Definition: TrackUnit.h:38
TInterface::ReselectUserGraphicClick
void __fastcall ReselectUserGraphicClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12315
TInterface::TTClockAdd1mButtonClick
void __fastcall TTClockAdd1mButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11930
TInterface::SubMinsButton
TButton * SubMinsButton
Definition: InterfaceUnit.h:142
TInterface::SpeedButton66
TSpeedButton * SpeedButton66
Definition: InterfaceUnit.h:570
TTrack::PlotPlainRaisedLinkedLevelCrossingBarriersAndSetMarkers
void PlotPlainRaisedLinkedLevelCrossingBarriersAndSetMarkers(int Caller, int BaseElementSpeedTag, int HLoc, int VLoc, TDisplay *Disp)
Plot LC elements without any base elements, and set LCPlotted true - used in ClearandRebuildRailway.
Definition: TrackUnit.cpp:6404
TInterface::ValidateTimetableButtonClick
void __fastcall ValidateTimetableButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4187
TInterface::UserGraphicMoveVPos
int UserGraphicMoveVPos
used to store the original user graphic 'H' & 'V' positions for use during moving
Definition: InterfaceUnit.h:1102
TInterface::SpeedButton98
TSpeedButton * SpeedButton98
Definition: InterfaceUnit.h:602
TActionVectorEntry::LocationName
AnsiString LocationName
Definition: TrainUnit.h:96
TInterface::LoadTimetableMenuItem
TMenuItem * LoadTimetableMenuItem
Definition: InterfaceUnit.h:413
TInterface::SpeedButton95
TSpeedButton * SpeedButton95
Definition: InterfaceUnit.h:599
TInterface::LocationNameButtonClick
void __fastcall LocationNameButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1133
TTrack::InactiveTrackElementPresentAtHV
bool InactiveTrackElementPresentAtHV(int Caller, int HLoc, int VLoc)
New at v1.2.0; true if an inactive track element present.
Definition: TrackUnit.cpp:5174
TInterface::SaveMenuItem
TMenuItem * SaveMenuItem
Definition: InterfaceUnit.h:412
TInterface::GapSetting
@ GapSetting
Definition: InterfaceUnit.h:881
TTrain::TimeTimeLocArrived
bool TimeTimeLocArrived
indicates whether has arrived (true) or not when ActionVectorEntryPtr->FormatType == TimeTimeLoc
Definition: TrainUnit.h:294
TInterface::ShowHideTTButton
TBitBtn * ShowHideTTButton
Definition: InterfaceUnit.h:124
TInterface::ScreenDownButton
TBitBtn * ScreenDownButton
Definition: InterfaceUnit.h:252
TTrain::LeadEntryPos
int LeadEntryPos
Definition: TrainUnit.h:327
TTrack::OverrideAndHideSignalBridgeMessage
bool OverrideAndHideSignalBridgeMessage
if false signals facing bridges are not permitted, but can be set to true using CTRL ALT 5
Definition: TrackUnit.h:664
TTrainController::LateArrivals
int LateArrivals
Definition: TrainUnit.h:768
TInterface::DeleteOnePrefDirButton
TBitBtn * DeleteOnePrefDirButton
Definition: InterfaceUnit.h:117
TInterface::PauseEntryTTClockSpeed
float PauseEntryTTClockSpeed
rate at which the timetable clock runs on entry to the adjust routine - to restore if cancelled
Definition: InterfaceUnit.h:1033
TTrainController::ReplotTrains
void ReplotTrains(int Caller, TDisplay *Disp)
plot all trains on the display
Definition: TrainUnit.cpp:8294
TInterface::MetreVariableLabel
TLabel * MetreVariableLabel
Definition: InterfaceUnit.h:103
TInterface::AllEntriesTTListBoxTopPosition
int AllEntriesTTListBoxTopPosition
stores the TopIndex property when keys are used to select items in the TT edit panel
Definition: InterfaceUnit.h:1052
TInterface::SigImagePanel
TPanel * SigImagePanel
new at v2.3.0 for handed signals
Definition: InterfaceUnit.h:387
TTrain::FloatingTimetableString
AnsiString FloatingTimetableString(int Caller, TActionVectorEntry *Ptr)
Used in the floating window to display the timetable.
Definition: TrainUnit.cpp:6590
TTrack::CopyFlag
bool CopyFlag
true only when copying a selection, used to prevent location names being copied
Definition: TrackUnit.h:644
TInterface::CPGenFileButtonClick
void __fastcall CPGenFileButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:12412
TAllRoutes::GetModifiableRouteAt
TOneRoute & GetModifiableRouteAt(int Caller, int At)
Returns a modifiable reference to the route at AllRoutesVector position 'At', after performing range ...
Definition: TrackUnit.cpp:16190
TInterface::TTClockAdd10mButtonClick
void __fastcall TTClockAdd10mButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11910
TRailGraphics::SpeedBut73GrndBlackGlyph
Graphics::TBitmap * SpeedBut73GrndBlackGlyph
Definition: GraphicUnit.h:1057
TTrain::AValue
double AValue
this is a useful shorthand value in calculating speeds and transit times in SetTrainMovementValues [=...
Definition: TrainUnit.h:373
TTrack::CheckMapAndTrack
void CheckMapAndTrack(int Caller)
Validity test.
Definition: TrackUnit.cpp:6899
TTrack::LoadGraphics
void LoadGraphics(int Caller, std::ifstream &VecFile, UnicodeString GraphicsPath)
new at v2.4.0, load user graphics
Definition: TrackUnit.cpp:2724
TTrainController::WriteTrainsToImage
void WriteTrainsToImage(int Caller, Graphics::TBitmap *Bitmap)
Called by TInterface::SaveOperatingImage1Click) to write all trains to the image file.
Definition: TrainUnit.cpp:8309
TInterface::SpeedButton30
TSpeedButton * SpeedButton30
Definition: InterfaceUnit.h:534
TTrackElement::LocationName
AnsiString LocationName
location name not used for timetabling, only for identification: platforms, non-station named locatio...
Definition: TrackUnit.h:130
TInterface::TTClockSpeedLabel
TLabel * TTClockSpeedLabel
Definition: InterfaceUnit.h:329
TTrack::FourAspectBuild
@ FourAspectBuild
Definition: TrackUnit.h:757
TInterface::SpeedButton146
TSpeedButton * SpeedButton146
Definition: InterfaceUnit.h:650
TTrainController::OpTimeToActMultiMapIterator
TOpTimeToActMultiMapIterator OpTimeToActMultiMapIterator
added v2.2.0 for Op time to act display
Definition: TrainUnit.h:803
TTrack::TActiveLevelCrossing::HLoc
int HLoc
HLoc value for found level crossing element.
Definition: TrackUnit.h:540
TInterface::NewEntryInPreparationFlag
bool NewEntryInPreparationFlag
true when a new timetable entry is being prepared in the timetable editor
Definition: InterfaceUnit.h:953
TDisplay::DisplayOffsetH
static int DisplayOffsetH
the horizontal offset of the displayed screen
Definition: DisplayUnit.h:76
TInterface::OAPanelLabel
TLabel * OAPanelLabel
Definition: InterfaceUnit.h:334
TInterface::GetVersion
UnicodeString GetVersion()
determined automatically from the project options 'Version Info'
Definition: InterfaceUnit.cpp:811
TInterface::OneEntryTimetableContents
AnsiString OneEntryTimetableContents
the current text in the large right hand timetable edit window
Definition: InterfaceUnit.h:910
TInterface::SelectRect
TRect SelectRect
the rectangle in HLoc & VLoc terms set in Edit->Select & Edit->Reselect
Definition: InterfaceUnit.h:1135
TTrain::ZeroPowerNoJoinedByMessage
bool ZeroPowerNoJoinedByMessage
Definition: TrainUnit.h:303
TInterface::LocationNameComboBox
TComboBox * LocationNameComboBox
the combobox that lists location names
Definition: InterfaceUnit.h:173
TInterface::ValidateTimetableKeyFlag
bool ValidateTimetableKeyFlag
Definition: InterfaceUnit.h:1023
TTrack::SkipLocationNameMultiMapCheck
bool SkipLocationNameMultiMapCheck
changed from PastingWithAttributes in v2.4.0 as all pastes are now with attributes - needed to suppre...
Definition: TrackUnit.h:662
TInterface::ExitOperationButton
TBitBtn * ExitOperationButton
Definition: InterfaceUnit.h:203
TTrain::CalcTimeToAct
float CalcTimeToAct(int Caller)
new v2.2.0 for operator action panel. Calculates the time left for operator action to avoid unnecessa...
Definition: TrainUnit.cpp:7690
TInterface::TTLabel6
TLabel * TTLabel6
Definition: InterfaceUnit.h:344
TInterface::SpeedButton97
TSpeedButton * SpeedButton97
Definition: InterfaceUnit.h:601
TTrainController::SaveSessionContinuationAutoSigEntries
void SaveSessionContinuationAutoSigEntries(int Caller, std::ofstream &SessionFile)
save ContinuationAutoSigEntries to a session file
Definition: TrainUnit.cpp:14193
TInterface::SignalStopImage
TImage * SignalStopImage
Definition: InterfaceUnit.h:265
TInterface::SpeedButton13
TSpeedButton * SpeedButton13
Definition: InterfaceUnit.h:517
TInterface::OutputLog9
TLabel * OutputLog9
Definition: InterfaceUnit.h:300
TInterface::SetCaption
void SetCaption(int Caller)
Sets the railway and timetable titles at the top of the screen.
Definition: InterfaceUnit.cpp:15682
TInterface::SpeedButton27
TSpeedButton * SpeedButton27
Definition: InterfaceUnit.h:531
TOnePrefDir::ExternalClearPrefDirAnd4MultiMap
void ExternalClearPrefDirAnd4MultiMap()
Empty the existing preferred direction vector & map - for use by other classes.
Definition: TrackUnit.h:1287
TInterface::SetInitialPrefDirModeEditMenu
void SetInitialPrefDirModeEditMenu()
Enables or disables the initial Edit mode submenu items in PrefDir mode.
Definition: InterfaceUnit.cpp:18378
TInterface::MainScreenMouseMove
void __fastcall MainScreenMouseMove(TObject *Sender, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:7165
TInterface::DistanceContinuing
@ DistanceContinuing
Definition: InterfaceUnit.h:881
TTrack::TUserGraphicMapEntry
std::pair< AnsiString, TPicture * > TUserGraphicMapEntry
an entry for TUserGraphicMap
Definition: TrackUnit.h:565
TInterface::CutTTEntryKeyFlag
bool CutTTEntryKeyFlag
Definition: InterfaceUnit.h:1017
TInterface::SigsOnLeftImage2
TImage * SigsOnLeftImage2
Definition: InterfaceUnit.h:281
TInterface::ChainEdit
TEdit * ChainEdit
Definition: InterfaceUnit.h:99
TInterface::SpeedButton109
TSpeedButton * SpeedButton109
Definition: InterfaceUnit.h:613
TInterface::CPAtLocCheckBox
TCheckBox * CPAtLocCheckBox
Definition: InterfaceUnit.h:244
TInterface::PasteTTEntryButtonClick
void __fastcall PasteTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3736
TInterface::SpeedButton100
TSpeedButton * SpeedButton100
Definition: InterfaceUnit.h:604
TInterface::TestFunction
void TestFunction()
Called for diagnostic purposes when keys CTRL ALT 4 pressed.
Definition: InterfaceUnit.cpp:18478
TInterface::ExportTTKeyFlag
bool ExportTTKeyFlag
Definition: InterfaceUnit.h:1027
TOnePrefDir::GetNextPrefDirElement
bool GetNextPrefDirElement(int Caller, int HLoc, int VLoc, bool &FinishElement)
Used when continuing a chain of preferred directions or element lengths. Tries to find a set of linke...
Definition: TrackUnit.cpp:10489
TTrain::FirstHalfMove
bool FirstHalfMove
true when the train is on the first half of an element when it displays as fully on two elements....
Definition: TrainUnit.h:349
TInterface::MovingTrainPresentOnFlashingRoute
bool MovingTrainPresentOnFlashingRoute(int Caller)
Examines a flashing route (i.e. one being set) and returns true if a moving train is detected on it a...
Definition: InterfaceUnit.cpp:12894
TInterface::Level2TrackMode
enum TInterface::TLevel2TrackMode Level2TrackMode
TInterface::SpeedButton65
TSpeedButton * SpeedButton65
Definition: InterfaceUnit.h:569
TInterface::DeleteTTEntryKeyFlag
bool DeleteTTEntryKeyFlag
Definition: InterfaceUnit.h:1019
TTrainController::LatePasses
int LatePasses
Definition: TrainUnit.h:770
TInterface::SaveRailwayBaseModeButton
TBitBtn * SaveRailwayBaseModeButton
Save button at the top left hand corner of the screen when no mode is selected.
Definition: InterfaceUnit.h:59
TInterface::SelectBiDirPrefDirsMenuItem
TMenuItem * SelectBiDirPrefDirsMenuItem
Definition: InterfaceUnit.h:440
TInterface::UserGraphicReselectPanel
TPanel * UserGraphicReselectPanel
Definition: InterfaceUnit.h:483
TFixedTrackPiece::TrackType
TTrackType TrackType
the type of track element
Definition: TrackUnit.h:98
TInterface::RotLeftMenuItem
TMenuItem * RotLeftMenuItem
Definition: InterfaceUnit.h:476
TInterface::TTClockxQuarterButtonClick
void __fastcall TTClockxQuarterButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11834
TTrainController::SSHigh
bool SSHigh
Definition: TrainUnit.h:743
TInterface::TextOrUserGraphicGridVal
int TextOrUserGraphicGridVal
stores the text alignment grid value, cycles forwards through 1, 2, 4, 8 & 16 each time the text grid...
Definition: InterfaceUnit.h:1094
TimeLoc
@ TimeLoc
Definition: TrainUnit.h:62
TPrefDirElement
Basic preferred direction or route element - track element with additional members.
Definition: TrackUnit.h:210
TInterface::FileMenu
TMenuItem * FileMenu
Definition: InterfaceUnit.h:409
TTrainController::AvHoursIntValue
int AvHoursIntValue
Input in MTBFEditBox in timetable hours, min value is 1 and max is 10,000. Here because performance f...
Definition: TrainUnit.h:788
TTrainController::CrashedTrains
int CrashedTrains
Definition: TrainUnit.h:763
TInterface::OutputLog3MouseDown
void __fastcall OutputLog3MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
Definition: InterfaceUnit.cpp:11099
TInterface::SpeedConversionPanel
TPanel * SpeedConversionPanel
Definition: InterfaceUnit.h:106
TTrainController::TTEditPanelVisible
bool TTEditPanelVisible
new at v2.6.0 so potential error message only shows in TTEdit mode
Definition: TrainUnit.h:741
TTrain::LogAction
void LogAction(int Caller, AnsiString HeadCode, AnsiString OtherHeadCode, TActionType ActionType, AnsiString LocationName, TDateTime TimetableNonRepeatTime, bool Warning)
Send a message to the performance log and performance file, and if the message is flagged as a warnin...
Definition: TrainUnit.cpp:4795
TTrack::PlotLCBaseElementsOnly
void PlotLCBaseElementsOnly(int Caller, TBarrierState State, int BaseElementSpeedTag, int HLoc, int VLoc, int ConsecSignals, TDisplay *Disp)
Just replot the basic track elements at a level crossing (for flashing)
Definition: TrackUnit.cpp:6478
TInterface::SpeedButton22
TSpeedButton * SpeedButton22
Definition: InterfaceUnit.h:526
TTextHandler::SaveText
void SaveText(int Caller, std::ofstream &VecFile)
save the railway's text to VecFile
Definition: TextUnit.cpp:319
TTrain::StoppedAtSignal
bool StoppedAtSignal
Definition: TrainUnit.h:432
TInterface::SpeedButton130
TSpeedButton * SpeedButton130
Definition: InterfaceUnit.h:634
TTrack::GetGapHLoc
int GetGapHLoc()
Definition: TrackUnit.h:760
TInterface::ResetDefaultLengthButton
TBitBtn * ResetDefaultLengthButton
Definition: InterfaceUnit.h:78
TTrackElement::Attribute
int Attribute
special variable used only for points, signals & level crossings, ignored otherwise; points 0=set to ...
Definition: TrackUnit.h:139
TInterface::PauseEntryRestartTime
double PauseEntryRestartTime
time value of the timetable restart time (as a double) on entry to pause mode
Definition: InterfaceUnit.h:1030
TInterface::SelectBiDirPrefDirsMenuItemClick
void __fastcall SelectBiDirPrefDirsMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9602
TRailGraphics::SetUpAllDerivitiveGraphics
void SetUpAllDerivitiveGraphics(TColor TransparentColour)
Definition: GraphicUnit.cpp:4136
TInterface::SigsOnRightImage2
TImage * SigsOnRightImage2
Definition: InterfaceUnit.h:283
TTrack::LocationNameMultiMap
TLocationNameMultiMap LocationNameMultiMap
multimap of location names (see type for more information above)
Definition: TrackUnit.h:703
TTrack::NoNamedLocationElements
bool NoNamedLocationElements(int Caller)
True if there are no NamedLocationElements (includes footcrossings)
Definition: TrackUnit.cpp:4106
TInterface::AddTrack
@ AddTrack
Definition: InterfaceUnit.h:881
TTrack::EraseTrackElement
void EraseTrackElement(int Caller, int HLocInput, int VLocInput, int &ErasedTrackVectorPosition, bool &TrackEraseSuccessfulFlag, bool InternalChecks)
Erases all active and inactive track elements at HLocInput & VLocInput from the vectors,...
Definition: TrackUnit.cpp:1670
TInterface::ClearAllMenuItem
TMenuItem * ClearAllMenuItem
Definition: InterfaceUnit.h:416
TTrainController::THCandTrainPosParam
std::pair< AnsiString, int > THCandTrainPosParam
Definition: TrainUnit.h:714
TInterface::SaveImageNoGridMenuItem
TMenuItem * SaveImageNoGridMenuItem
Definition: InterfaceUnit.h:451
TInterface::SelectMenuItemClick
void __fastcall SelectMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8839
TRailGraphics::SpeedBut74NormBlackGlyph
Graphics::TBitmap * SpeedBut74NormBlackGlyph
Definition: GraphicUnit.h:1050
TInterface::StartY
int StartY
the mouse position in terms of pixels when an item of text is being selected for moving
Definition: InterfaceUnit.h:1086
FootCrossing
@ FootCrossing
Definition: TrackUnit.h:63
TInterface::UpdateOperatorActionPanel
void UpdateOperatorActionPanel(int Caller)
Called every 5 secs to update the panel (if visible)
Definition: InterfaceUnit.cpp:18576
TInterface::TextBoxKeyPress
void __fastcall TextBoxKeyPress(TObject *Sender, char &Key)
Definition: InterfaceUnit.cpp:1093
TInterface::SaveTimetableToSessionFile
bool SaveTimetableToSessionFile(int Caller, std::ofstream &SessionFile, AnsiString SessionFileStr)
Called during a session save to save the current timetable in the session file, true if successful.
Definition: InterfaceUnit.cpp:16622
TInterface::SpeedButton71
TSpeedButton * SpeedButton71
Definition: InterfaceUnit.h:575
TTrack::IsLCAtHV
bool IsLCAtHV(int Caller, int HLoc, int VLoc)
True if a level crossing is found at H & V.
Definition: TrackUnit.cpp:6650
TTrain::OpTimeToAct
float OpTimeToAct
in minutes: new at v2.2.0 for operator time to act panel. Calculated in UpdateTrain,...
Definition: TrainUnit.h:402
TInterface::DeleteAllPrefDirButtonClick
void __fastcall DeleteAllPrefDirButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1935
Platform
@ Platform
Definition: TrackUnit.h:63
TInterface::RlyFile
bool RlyFile
indicates that a loaded railway file is ready for operation, i.e. is a valid .rly file
Definition: InterfaceUnit.h:963
TInterface::RestartSessionOperMode
@ RestartSessionOperMode
Definition: InterfaceUnit.h:851
TInterface::PreferredRouteFlag
bool PreferredRouteFlag
used to select either ConvertAndAddPreferredRouteSearchVector or ConvertAndAddNonPreferredRouteSearch...
Definition: InterfaceUnit.h:959
TTrack::LevelCrossingBarrierDownFlashDuration
float LevelCrossingBarrierDownFlashDuration
duration of the flash period when level crossing opening
Definition: TrackUnit.h:668
TInterface::TextMoveHPos
int TextMoveHPos
Definition: InterfaceUnit.h:1098
TTrack::LocationsNotNamed
bool LocationsNotNamed(int Caller)
True if there are unnamed NamedLocationElements (includes footcrossings)
Definition: TrackUnit.cpp:4131
TTrainController::TTClockTime
TDateTime TTClockTime
the time indicated by the timetable clock
Definition: TrainUnit.h:640
TInterface::PowerTopLabel
TLabel * PowerTopLabel
Definition: InterfaceUnit.h:188
TTrack::RotLeftArray
int RotLeftArray[FirstUnusedSpeedTagNumber]
holds TrackElement SpeedTag values for 'rotating left' via menu items 'Edit' & 'Rotate left'
Definition: TrackUnit.h:679
TInterface::SpeedButton129
TSpeedButton * SpeedButton129
Definition: InterfaceUnit.h:633
TInterface::RepairFailedTrainMenuItem
TMenuItem * RepairFailedTrainMenuItem
Definition: InterfaceUnit.h:478
TUtilities::CheckAndCompareFileString
bool CheckAndCompareFileString(std::ifstream &InFile, AnsiString InString)
checks that the value is a string ('0' or CR accepted as delimiters) and is the same as InString,...
Definition: Utilities.cpp:413
TInterface::CutTTEntryButton
TButton * CutTTEntryButton
Definition: InterfaceUnit.h:131
TInterface::AZOrderKeyFlag
bool AZOrderKeyFlag
Definition: InterfaceUnit.h:1021
TInterface::MileEdit
TEdit * MileEdit
Definition: InterfaceUnit.h:98
TOnePrefDir
The basic preferred direction class, consisting of any number of elements with preferred directions s...
Definition: TrackUnit.h:1193
TInterface::TTClockx8ButtonClick
void __fastcall TTClockx8ButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11758
TInterface::SetLevel2OperMode
void SetLevel2OperMode(int Caller)
Sets the Level2OperMode user mode, using the Level2OperMode variable to determine the mode.
Definition: InterfaceUnit.cpp:14117
TTrack::NonFootCrossingNamedLocationExists
bool NonFootCrossingNamedLocationExists(int Caller)
True if there is a platform, NamedNonStationLocation or Concourse present in the railway.
Definition: TrackUnit.cpp:8637
TInterface::RestoreTTButton
TButton * RestoreTTButton
Definition: InterfaceUnit.h:147
TTrain::TimetableFinished
bool TimetableFinished
set when there are no more timetable actions
Definition: TrainUnit.h:369
TGraphicElement::SetScreenHVSource
void SetScreenHVSource(int Caller, int HPosIn, int VPosIn)
Set HPos, VPos & SourceRect member values from the supplied positions.
Definition: TrackUnit.cpp:1484
TInterface::EraseLocationNameText
bool EraseLocationNameText(int Caller, AnsiString Name, int &HPos, int &VPos)
Erase a location name (providing it exists in LocationNameMultiMap) from TextVector,...
Definition: InterfaceUnit.cpp:18420
TInterface::PrefDirKey
TImage * PrefDirKey
information panel displayed when setting preferred directions
Definition: InterfaceUnit.h:270
TUtilities::CallLog
std::deque< AnsiString > CallLog
call stack store, saved to the errorlog for diagnostic purposes
Definition: Utilities.h:55
TActionVectorEntry::Command
AnsiString Command
Definition: TrainUnit.h:96
TInterface::SpeedButton138
TSpeedButton * SpeedButton138
Definition: InterfaceUnit.h:642
TTrack::UserGraphicVector
TUserGraphicVector UserGraphicVector
Definition: TrackUnit.h:705
TTrackElement::Length23
int Length23
Definition: TrackUnit.h:147
TInterface::DeleteAllPrefDirButton
TBitBtn * DeleteAllPrefDirButton
Definition: InterfaceUnit.h:118
TInterface::SpeedButton117
TSpeedButton * SpeedButton117
Definition: InterfaceUnit.h:621
TTrain::SignallerStoppingFlag
bool SignallerStoppingFlag
set when the signaller stop command has been given
Definition: TrainUnit.h:361
TUtilities::LoadFileBool
bool LoadFileBool(std::ifstream &InFile)
loads a bool value from the file
Definition: Utilities.cpp:141
TInterface::SpeedButton39
TSpeedButton * SpeedButton39
Definition: InterfaceUnit.h:543
TTrack::BuildBasicElementFromSpeedTag
TTrackElement BuildBasicElementFromSpeedTag(int Caller, int SpeedTag)
Return a basic track element from the SpeedTag new at v2.2.0 - needed because Interface doesn't have ...
Definition: TrackUnit.h:812
TInterface::TTStartTimeBox
TEdit * TTStartTimeBox
edit box that displays the timetable start time
Definition: InterfaceUnit.h:171
TInterface::AddPrefDirButtonClick
void __fastcall AddPrefDirButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1908
TInterface::ShiftKey
bool ShiftKey
true when the SHIFT key is pressed (see also CtrlKey)
Definition: InterfaceUnit.h:977
TTrainController::SigSLow
bool SigSLow
Message flags in TT checks to stop being given twice.
Definition: TrainUnit.h:743
TTrack::TActiveLevelCrossing
Definition: TrackUnit.h:527
TTrack::AnyLinkedBarrierDownVectorManual
bool AnyLinkedBarrierDownVectorManual(int Caller, int HLoc, int VLoc, int &BDVectorPos)
Checks BarrierDownVector and returns true if there is one that is linked to the LC at H & V positions...
Definition: TrackUnit.cpp:5689
TInterface::AddMinsButtonClick
void __fastcall AddMinsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3469
RemoveTrain
@ RemoveTrain
Definition: TrainUnit.h:50
TTrack::SaveSessionBarriersDownVector
void SaveSessionBarriersDownVector(int Caller, std::ofstream &OutFile)
Save all vector values to the session file.
Definition: TrackUnit.cpp:3218
TInterface::FontButtonClick
void __fastcall FontButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1839
TDisplay::PlotAndAddUserGraphic
void PlotAndAddUserGraphic(int Caller, TUserGraphicItem UserGraphicItem)
Plot user graphic.
Definition: DisplayUnit.cpp:98
TInterface::SigAspectButtonClick
void __fastcall SigAspectButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1800
TInterface::SetLevel2TrackMode
void SetLevel2TrackMode(int Caller)
Sets the Level2TrackMode user mode, using the Level2TrackMode variable to determine the mode.
Definition: InterfaceUnit.cpp:13492
TTrainController::SetWarningFlags
void SetWarningFlags(int Caller)
This sets all the warning flags (CrashWarning, DerailWarning etc) to their required states after a se...
Definition: TrainUnit.cpp:17236
TInterface::None
@ None
Definition: InterfaceUnit.h:886
TInterface::SpeedButton87
TSpeedButton * SpeedButton87
Definition: InterfaceUnit.h:591
TDisplay::PlotSmallOutput
void PlotSmallOutput(int Caller, int HPos, int VPos, Graphics::TBitmap *PlotItem)
Plot small (4x4) graphic PlotItem on the zoomed-out display at HPos & Vpos.
Definition: DisplayUnit.cpp:111
TInterface::FormClose
void __fastcall FormClose(TObject *Sender, TCloseAction &Action)
Definition: InterfaceUnit.cpp:10508
TInterface::SigAspectButton
TBitBtn * SigAspectButton
Definition: InterfaceUnit.h:75
TTrack::SelectVectorAt
TTrackElement & SelectVectorAt(int Caller, int At)
A range-checked version of SelectVector.at(At)
Definition: TrackUnit.cpp:9962
TTrack::LCChangeFlag
bool LCChangeFlag
true when LCs changing
Definition: TrackUnit.h:650
TInterface::PreviousTTEntryKeyFlag
bool PreviousTTEntryKeyFlag
Definition: InterfaceUnit.h:1012
TInterface::CPEditDepRange
TEdit * CPEditDepRange
Definition: InterfaceUnit.h:246
TInterface::SpeedButton127
TSpeedButton * SpeedButton127
Definition: InterfaceUnit.h:631
TTrainController::TotEarlyPassMins
float TotEarlyPassMins
Definition: TrainUnit.h:757
TTrainController::OpTimeToActMultiMap
TOpTimeToActMultiMap OpTimeToActMultiMap
added v2.2.0 for Op time to act display
Definition: TrainUnit.h:801
TInterface::SelectBitmapMouseLocY
int SelectBitmapMouseLocY
see above
Definition: InterfaceUnit.h:1076
TTrain::BrakeRate
double BrakeRate
the current train brake rate
Definition: TrainUnit.h:391
TTrackElement::SpeedLimit23
int SpeedLimit23
Element lengths and speed limits, ...01 is for the track with link positions [0] and [1],...
Definition: TrackUnit.h:147
TTrack::GapFlashFlag
bool GapFlashFlag
true when a pair of connected gaps is flashing
Definition: TrackUnit.h:648
TTrack::TActiveLevelCrossing::ChangeDuration
float ChangeDuration
duration of the level crossing changing period
Definition: TrackUnit.h:536
TDisplay::DisplayOffsetVHome
static int DisplayOffsetVHome
the vertical offset of the 'Home' display
Definition: DisplayUnit.h:82
TInterface::StartX
int StartX
Definition: InterfaceUnit.h:1086
TrainUnit.h
TTrack::LevelCrossingBarrierUpFlashDuration
float LevelCrossingBarrierUpFlashDuration
duration of the flash period when level crossing closing to trains
Definition: TrackUnit.h:666
TTrainController::IncorrectExits
int IncorrectExits
Definition: TrainUnit.h:767
TUtilities::SetLocaleResultOK
bool SetLocaleResultOK
flag to indicate whether the call to setlocale() in InterfaceUnit.cpp succeeded or not
Definition: Utilities.h:42
TInterface::SelectLengthsFlag
bool SelectLengthsFlag
true when 'Set lengths &/or speeds' selected in the 'Edit' menu
Definition: InterfaceUnit.h:973
TFixedTrackPiece::Link
int Link[4]
Track connection link values, max. of 4, unused = -1, top lh diag.=1, top=2, top rh diag....
Definition: TrackUnit.h:87
TRailGraphics::LockedRouteCancelPtr
Graphics::TBitmap * LockedRouteCancelPtr[10]
for locked route cancel graphic, 1 for each of 8 links, 0 & 5 included as for direction
Definition: GraphicUnit.h:1036
TInterface::TrackOKButton
TBitBtn * TrackOKButton
Definition: InterfaceUnit.h:65
TInterface::SpeedButton23
TSpeedButton * SpeedButton23
Definition: InterfaceUnit.h:527
TInterface::RailwayTitle
AnsiString RailwayTitle
Definition: InterfaceUnit.h:914
TDisplay::Rectangle
void Rectangle(int Caller, int HPos, int VPos, TColor Col, int Size, int Width)
Plot a rectangle at the defined position with colour Col & size defined by Size.
Definition: DisplayUnit.cpp:152
TInterface::SpeedButton20
TSpeedButton * SpeedButton20
Definition: InterfaceUnit.h:524
TInterface::CheckInterface
bool CheckInterface(int Caller, std::ifstream &SessionFile)
Check the interface part of a session file & return false for error, called during SessionFileIntegri...
Definition: InterfaceUnit.cpp:16388
TInterface::PreStart
@ PreStart
Definition: InterfaceUnit.h:873
AboutForm
TAboutForm * AboutForm
Definition: AboutUnit.cpp:47
TInterface::SpeedButton137
TSpeedButton * SpeedButton137
Definition: InterfaceUnit.h:641
TInterface::ExitTTModeButton
TBitBtn * ExitTTModeButton
Definition: InterfaceUnit.h:125
TTrain::SetTrainMovementValues
void SetTrainMovementValues(int Caller, int TrackVectorPosition, int EntryPos)
Calculates train speeds and times for the element that the train is about to enter....
Definition: TrainUnit.cpp:3300
TActionVectorEntry::Warning
bool Warning
if set triggers an alert in the warning panel when the action is reached
Definition: TrainUnit.h:100
TInterface::OverallSpeedLimit
int OverallSpeedLimit
and the overall speed limit, if the speed limits vary across the selection the value is set to -1
Definition: InterfaceUnit.h:1064
TOnePrefDir::GetFixedSearchElementAt
const TPrefDirElement & GetFixedSearchElementAt(int Caller, int At) const
Return a non-modifiable element at SearchVector position 'At'.
Definition: TrackUnit.cpp:10423
TInterface::SpeedButton78
TSpeedButton * SpeedButton78
Definition: InterfaceUnit.h:582
TRailGraphics::SpeedBut75GrndBlackGlyph
Graphics::TBitmap * SpeedBut75GrndBlackGlyph
Definition: GraphicUnit.h:1059
TTrainDataEntry::ServiceReference
AnsiString ServiceReference
Definition: TrainUnit.h:179
TInterface::PowerEditBox
TEdit * PowerEditBox
Definition: InterfaceUnit.h:187
TInterface::TimetableHandler
void TimetableHandler()
Called during timetable editing whenever a change is made to the timetable, sets all the timetable bu...
Definition: InterfaceUnit.cpp:5105
TTrain::SignallerChangeTrainDirection
void SignallerChangeTrainDirection(int Caller)
Unplots & replots train, which checks for facing signal and sets StoppedAtSignal if req'd.
Definition: TrainUnit.cpp:6364
TTextHandler::TextErase
bool TextErase(int Caller, int HPosition, int VPosition, AnsiString TextToErase)
look for a text item in the vicinity of HPosInput & VPosInput & if TextToErase is null then erase any...
Definition: TextUnit.cpp:250
TInterface::CancelSelectionMenuItem
TMenuItem * CancelSelectionMenuItem
Definition: InterfaceUnit.h:441
TTrain::ZeroPowerNoRearSplitMessage
bool ZeroPowerNoRearSplitMessage
Definition: TrainUnit.h:301
TInterface::SpeedButton68
TSpeedButton * SpeedButton68
Definition: InterfaceUnit.h:572
TInterface::LoadSession
void LoadSession(int Caller)
Load a session file.
Definition: InterfaceUnit.cpp:16029
TAllRoutes::GetAllRoutesTruncateElement
bool GetAllRoutesTruncateElement(int Caller, int HLoc, int VLoc, bool ConsecSignalsRoute)
Examines all routes and for each uses GetRouteTruncateElement to see if the element at H & V is prese...
Definition: TrackUnit.cpp:16230
TAllRoutes::SetTrailingSignalsOnContinuationRoute
void SetTrailingSignalsOnContinuationRoute(int Caller, int RouteNumber, int AccessNumber)
This is called by the InterfaceUnit at intervals based on entries in the ContinuationAutoSigVector in...
Definition: TrackUnit.cpp:17237
TDisplay::DisplayZoomOutOffsetHHome
static int DisplayZoomOutOffsetHHome
the horizontal offset of the zoomed-out 'Home' display
Definition: DisplayUnit.h:88
TInterface::SigRouteStartMarker
TGraphicElement * SigRouteStartMarker
Definition: InterfaceUnit.h:1118
TInterface::SetGapsButtonClick
void __fastcall SetGapsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:1034
TInterface::SignallerControlStopMenuItemClick
void __fastcall SignallerControlStopMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:10184
TInterface::PrefDirSelecting
@ PrefDirSelecting
Definition: InterfaceUnit.h:877
TInterface::TimetableDialog
TOpenDialog * TimetableDialog
Definition: InterfaceUnit.h:490
TInterface::MissedTicks
unsigned int MissedTicks
missed clock ticks
Definition: InterfaceUnit.h:1050
TTrack::FindHighestLowestAndLeftmostNamedElements
bool FindHighestLowestAndLeftmostNamedElements(int Caller, AnsiString Name, int &VPosHi, int &VPosLo, int &HPos)
Used in locating the screen name position for a named location, return true if find an inactive eleme...
Definition: TrackUnit.cpp:9991
TInterface::MoveTTEntryUpButton
TButton * MoveTTEntryUpButton
Definition: InterfaceUnit.h:134
TInterface::RotateMenuItem
TMenuItem * RotateMenuItem
Definition: InterfaceUnit.h:436
TInterface::SpeedButton33
TSpeedButton * SpeedButton33
Definition: InterfaceUnit.h:537
TInterface::TTClockxSixteenthButtonClick
void __fastcall TTClockxSixteenthButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11871
TTrack::TIMPair
std::pair< unsigned int, unsigned int > TIMPair
TrackElement pair type used for inactive elements, values are vector positions.
Definition: TrackUnit.h:586
TTextHandler::TextVectorSize
unsigned int TextVectorSize(int Caller)
return the number of items in TextVector
Definition: TextUnit.cpp:505
TUtilities::Clock2Stopped
bool Clock2Stopped
when true the main loop - Interface->ClockTimer2 - is stopped
Definition: Utilities.h:38
TTrainController::MRSHigh
bool MRSHigh
Definition: TrainUnit.h:743
TInterface::FlipMenuItem
TMenuItem * FlipMenuItem
Definition: InterfaceUnit.h:434
TTrack::SetLinkedLevelCrossingBarrierAttributes
void SetLinkedLevelCrossingBarrierAttributes(int Caller, int HLoc, int VLoc, int Attr)
Set linked LC attributes; 0=closed to trains, 1 = open to trains, 2 = changing state = closed to trai...
Definition: TrackUnit.cpp:5591
TTrackElement::GroundSignal
@ GroundSignal
Definition: TrackUnit.h:156
TInterface::SessionFileIntegrityCheck
bool SessionFileIntegrityCheck(int Caller, AnsiString FileName)
Checks session file integrity prior to loading, true for success.
Definition: InterfaceUnit.cpp:17118
TInterface::TrainFailedImage
TImage * TrainFailedImage
Definition: InterfaceUnit.h:480
TTrain::NotInService
bool NotInService
Definition: TrainUnit.h:433
TInterface::RotLeftMenuItemClick
void __fastcall RotLeftMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9346
TInterface::SpeedButton14
TSpeedButton * SpeedButton14
Definition: InterfaceUnit.h:518
TInterface::ExitTrackButton
TBitBtn * ExitTrackButton
Definition: InterfaceUnit.h:76
TTrack::ActiveTrackElementNameMapCompiledFlag
bool ActiveTrackElementNameMapCompiledFlag
indicates that the ActiveTrackElementNameMap has been compiled
Definition: TrackUnit.h:642
TInterface::SpeedButton110
TSpeedButton * SpeedButton110
Definition: InterfaceUnit.h:614
Track
TTrack * Track
the object pointer, object created in InterfaceUnit
Definition: TrackUnit.cpp:53
TInterface::OutputLog10
TLabel * OutputLog10
Definition: InterfaceUnit.h:301
TInterface::SESSION_DIR_NAME
static const UnicodeString SESSION_DIR_NAME
Definition: InterfaceUnit.h:865
TInterface::PasteTTEntryKeyFlag
bool PasteTTEntryKeyFlag
Definition: InterfaceUnit.h:1018
TInterface::FileChangedFlag
bool FileChangedFlag
true when a loaded railway file has changed (used to warn user if opts to exit without saving)
Definition: InterfaceUnit.h:941
TTrackElement::Conn
int Conn[4]
Connecting element position in TrackVector, set to -1 if no connecting link or if track not linked.
Definition: TrackUnit.h:141
TInterface::CutTTEntryButtonClick
void __fastcall CutTTEntryButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:3662
TInterface::AutoSigsButtonClick
void __fastcall AutoSigsButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2057
TRailGraphics::SpeedBut69GrndBlackGlyph
Graphics::TBitmap * SpeedBut69GrndBlackGlyph
Definition: GraphicUnit.h:1053
Signaller
@ Signaller
Definition: TrainUnit.h:56
TRailGraphics::bmRedRect
Graphics::TBitmap * bmRedRect
Definition: GraphicUnit.h:526
TInterface::SaveOperatingImageMenuItemClick
void __fastcall SaveOperatingImageMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:2789
TRailGraphics::smYellow
Graphics::TBitmap * smYellow
Definition: GraphicUnit.h:886
RailGraphics
TRailGraphics * RailGraphics
the object pointer, object created in InterfaceUnit
Definition: GraphicUnit.cpp:50
TInterface::ConstructRoute
TOneRoute * ConstructRoute
the route under construction
Definition: InterfaceUnit.h:1132
TInterface::SpeedButton118
TSpeedButton * SpeedButton118
Definition: InterfaceUnit.h:622
TTrack::PlotSmallRedGap
void PlotSmallRedGap(int Caller)
Plot on screen in zoomed-out mode and in gap setting mode a small red square corresponding to the gap...
Definition: TrackUnit.cpp:9318
Bridge
@ Bridge
Definition: TrackUnit.h:63
TInterface::DirOpenError
bool DirOpenError
true when one of the program subfolders doesn't already exist and can't be created
Definition: InterfaceUnit.h:935
TInterface::CutMenuItemClick
void __fastcall CutMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:8927
TInterface::SpeedButton38
TSpeedButton * SpeedButton38
Definition: InterfaceUnit.h:542
TInterface::ResetCurrentSpeedButton
void ResetCurrentSpeedButton(int Caller)
Resets the CurrentSpeedButton variable to zero and the 'Down' property to false.
Definition: InterfaceUnit.cpp:12883
TInterface::SpeedButton102
TSpeedButton * SpeedButton102
Definition: InterfaceUnit.h:606
TTrain::TimetableMaxRunningSpeed
double TimetableMaxRunningSpeed
the maximum train running speed when in timetable mode (see int SignallerMaxSpeed for signaller contr...
Definition: TrainUnit.h:383
TInterface::SpeedButton99
TSpeedButton * SpeedButton99
Definition: InterfaceUnit.h:603
clB0G0R0
#define clB0G0R0
Definition: GraphicUnit.h:36
TInterface::CPDeparturesCheckBox
TCheckBox * CPDeparturesCheckBox
Definition: InterfaceUnit.h:243
Buffers
@ Buffers
Definition: TrackUnit.h:63
TInterface::SelectGraphic
@ SelectGraphic
Definition: InterfaceUnit.h:881
TTextHandler::TextMove
void TextMove(int Caller, int HPosInput, int VPosInput, int &TextItem, int &TextMoveHPos, int &TextMoveVPos, bool &TextFoundFlag)
Definition: TextUnit.cpp:196
TUtilities::ScreenElementHeight
int ScreenElementHeight
height of display screen in elements
Definition: Utilities.h:50
clFrontCodeTimetable
#define clFrontCodeTimetable
Definition: GraphicUnit.h:296
TTrack::UserGraphicPresentAtHV
bool UserGraphicPresentAtHV(int Caller, int HPos, int VPos, int &UGIVectorPos)
checks if a user graphic present
Definition: TrackUnit.h:738
TOnePrefDir::GetPrefDirStartElement
bool GetPrefDirStartElement(int Caller, int HLoc, int VLoc)
Used when beginning a chain of preferred directions or element lengths. Enter with HLoc & VLoc set to...
Definition: TrackUnit.cpp:10447
TInterface::ExitTTModeButtonClick
void __fastcall ExitTTModeButtonClick(TObject *Sender)
Definition: InterfaceUnit.cpp:4559
TInterface::MirrorMenuItemClick
void __fastcall MirrorMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:9021
TInterface::SpeedButton11
TSpeedButton * SpeedButton11
Definition: InterfaceUnit.h:515
TOneRoute::GetNextNonPreferredRouteElement
bool GetNextNonPreferredRouteElement(int Caller, int HLoc, int VLoc, bool ConsecSignalsRoute, bool Callon, IDInt &ReqPosRouteID, bool &PointsChanged)
Try to find a set of linked tracks between the route start element and the one at HLoc & VLoc....
Definition: TrackUnit.cpp:14558
TInterface::SigPrefButton
TBitBtn * SigPrefButton
Definition: InterfaceUnit.h:196
TInterface::RouteNotStarted
@ RouteNotStarted
Definition: InterfaceUnit.h:886
TTrack::GapsUnset
bool GapsUnset(int Caller)
True if there are gaps in the railway and any are unset.
Definition: TrackUnit.cpp:4044
TInterface::SaveImageAndGridMenuItem
TMenuItem * SaveImageAndGridMenuItem
Definition: InterfaceUnit.h:452
TInterface::SpeedButton48
TSpeedButton * SpeedButton48
Definition: InterfaceUnit.h:552
TInterface::WhiteBgndMenuItemClick
void __fastcall WhiteBgndMenuItemClick(TObject *Sender)
Definition: InterfaceUnit.cpp:11248